search envelope-o feed check
Home Unanswered Active Tags New Question
user comment-o

Trial Version - User Limitation?

Asked by Thaddeus
1 year ago.

Operating under the Trial Agreement is there a limitation to the number of users that can view a component deployed in a non-production instance? The current behavior is the person who installed the library can view the deployed component but any other user gets an error in the promise when the dp.init() or dp.update() methods are called.

Answer posted by Dan Letecky [DayPilot]
1 year ago.

This is not caused by the trial version. There should be no difference when someone other than the developer views the component.

There are no error details visible in the screenshot but it it prints a Proxy object. In Vue3, objects that you make reactive will be replaced by a Proxy and that may not always be what you want. In case of DayPilot.Date objects, it disrupts the direct object comparison (see https://api.daypilot.org/daypilot-date-class/).

I recommend checking the stack trace to identify the source of the error. It could be caused by some user-specific data.

Comment posted by Thaddeus
1 year ago.

It is an issue with how the placeholder div id is being passed. One user has a 'debug' mode turned on, one does not.

Here is the code that is pulling the div id.

const root = this.template.querySelector(".thegantt");

The user that is in debug mode generates the following id: This one correctly renders

{"$$DomManualKey$$":true,"outerHTML":"<div class=\"thegantt\" style=\"width: 100%;\"></div>"}

The normal user (no debug mode) generates with the following id: This produces the error

{"$$HostElementKey$$":115,"$$DomManualKey$$":true}

Comment posted by Dan Letecky [DayPilot]
1 year ago.

OK, so this is Salesforce LWC.

It looks like Salesforce performs some heavy transformations and it's not possible to use this.template.querySelector() with the element ID. The same might apply to classes.

https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.create_components_dom_work

This document mentions this.refs as a way to access a specific element:

<template>
    <div lwc:ref="gantt"></div>
</template>
export default class extends LightningElement {
    renderedCallback() {
        const element = this.refs.gantt;
        const dp = new DayPilot.Scheduler(element, { ... });
    }
}

Comment posted by Thaddeus
1 year ago.

Yes, Salesforce LWC. That was attempted but produced the same result.

<template>
    <div lwc:ref="mainCalendar"></div>
</template>

Full javascript attached.

Neither using the refs or the querySelector() are producing the "outerHTML" key.

##This is the refs root {"$$HostElementKey$$":115}

Comment posted by Dan Letecky [DayPilot]
1 year ago.

Thanks for the update. Can you try adding lwc:dom="manual" attribute to the placeholder? That is necessary because the Scheduler modifies the placeholder content directly.

<template>
  <div lwc:ref="mainCalendar" lwc:dom="manual"></div>
</template>
Comment posted by Thaddeus
1 year ago.

Suggestion applied, but the behavior does not change.

This is the new Daypilot.Scheduler(id) being passed into the initialization.

##This is the refs root {"$$HostElementKey$$":115,"$$DomManualKey$$":true}

Comment posted by Dan Letecky [DayPilot]
1 year ago.

You may need to check this with salesforce support to see why it behaves differently in production mode.

As far as I can see your implementation follows the Salesforce third party integration example. But some additional settings might be required.

I've found this related issue but it's not exactly the same problem:
https://salesforce.stackexchange.com/questions/397017/new-lwcref-does-not-work

Comment posted by Thaddeus
1 year ago.

I've done a PoC on another javascript library that doesn't encounter this issue. It is a very similar concept to pulling the <div> id to pass to the constructor. This library parses the querySelector while in production more or not in production mode.

https://github.com/DHTMLX/salesforce-gantt-demo/blob/master/force-app/main/default/lwc/gantt/gantt.js

Does the dayPilot.Scheduler constructor require the 'outerHTML' tag to be passed in with the div id?

Comment posted by Dan Letecky [DayPilot]
1 year ago.

It looks like the object that this.template.querySelector() returns is not the actual DOM element but a Proxy object. You print it using JSON.stringify() which doesn't give you access to the object in the console. This way it only prints selected properties which are marked for export to JSON.

To get full access to the object, you can print it like this:

const root2 = this.refs.mainCalendar;
console.log('##This is the refs root ', root);  // note the comma

Then you will be able to browser the object properties in the console.

The DayPilot.Scheduler uses this object as a root for its own DOM structure. It adds elements using appendChild() and modifies some top-level styles.

It detects whether the argument is a DOM element by checking the "tagName" property. If it doesn't have a tagName property and it's not a string, it prints the following error message: "DayPilot.Scheduler() constructor requires the target element or its ID as a parameter".

Comment posted by Thaddeus
1 year ago.

First, really appreciate the help. It is most appreciated. After adding the console.log as suggested above the results in production mode vs. non-production mode are not too different. It looks like non-production mode created the whole DIV with the rendered data and Production Mode just created the shell of the DIV. Files attached.

So from a code perspective it is failing on the this.dp.init(). So the DIV placeholder was already established when the DayPilot.Scheduler() instance was created.

const root2 = this.refs.mainCalendar;
console.log('##This is the refs root ' + JSON.stringify(root2));
console.log('##This is the refs root ', root2);

console.log('##Before creating the scheduler ');
this.dp = new window.DayPilot.Scheduler(root2);
this.dp.snapToGrid = false;
this.dp.useEventBoxes = "Never";
this.dp.treeEnabled= true;
this.dp.treePreventParentUsage= true;
this.dp.heightSpec= "Max";
this.dp.height= 500;
this.dp.eventMovingStartEndEnabled= true;
this.dp.eventResizingStartEndEnabled= true;
this.dp.timeRangeSelectingStartEndEnabled= true;
this.dp.scale = "Week";
this.dp.timeHeaders= [
{groupBy: "Month", format: "MMMM yyyy"},
{groupBy: "Week", format: "d"}
];
this.dp.days = 365;
this.dp.cellWidthSpec="Fixed"
this.dp.cellWidth=40;

<removed the section where data is being loaded to keep this smaller>

this.dp.resources = resources;
this.dp.events.list = events;
this.dp.init();

Failure message at this point

'Error loading dayPilot' - Cannot read properties of undefined (reading 'indexOf')

Comment posted by Dan Letecky [DayPilot]
1 year ago.

Great, thanks for the update! It looks like we are moving forward.

Two important points:

1. The constructor itself doesn't do anything with the DOM. The structure is created in init().
2. Even the failed example created something inside the placeholder. This means the problem isn't with finding the target element - but something fails during the init(). It looks like it might be something trivial.

At this point, it would be helpful to get the full stack trace of the exception.

Can you try to post a screenshot of this expanded error message:

.catch((error) => {
  console.error(error);   //   <- this should print the stack trace
  this.dispatchEvent(
    new ShowToastEvent({
      title: "Error loading dayPilot",
      message: error.message,
      variant: "error"
    })
  );
});
Comment posted by Thaddeus
1 year ago.

Full stack trace of the exception attached

Comment posted by Thaddeus
1 year ago.

Here are some additional details from the stack trace

Comment posted by Dan Letecky [DayPilot]
1 year ago.

Thanks for the info.

Could you please give it a try with the latest sandbox build (2023.2.5562)?
https://release.daypilot.org/changes/js/

This issue should be fixed there.

Please let me know if the problem persists.

Comment posted by Thaddeus
1 year ago.

Works like a charm. Thank you very much! Once I get this all put together would you be interested in a sample LWC that you could use on your website? I can include a generic reference back to a Salesforce object model to provide an example of how to implement with an apex back end as well.

Comment posted by Dan Letecky [DayPilot]
1 year ago.

Great, thanks for the update!

The example sounds great, thank you! We'll be happy to hear from you at support@daypilot.org (just please reference this thread).

This question is more than 1 months old and has been closed. Please create a new question if you have anything to add.