How to add "esri/widgets/Widget" into "dijit/layout/*"

1060
4
02-22-2017 08:37 AM
deleted-user-iPdcWUgWcsoy
New Contributor III

Hey at all,

hi Rene Rubalcava

I need some help again at implementing custom widgets with TypeScript and base class "esri/widgets/Widget". I think I understand that working with TypeScript, JSX and Maquette. It seems to be that there is one important thing you have to keep in mind for developing. You have to hold a none virtual dom in your web app to render the virtual dom of your widget into it. Is that right?

In a couple of days I tried to render a widget based on "esri/widgets/Widget" into a "dijit/layout/StackContainer". The main problem is, that there is no "domNode". I tried several things to prepare the domNode.

  • Call the render() function
    • Nothing happened. domNode ist still undefined
  • Create a "dijit/layout/ContentPane", add it to StackContainer and than call widget._projector.merge(contentPane.domNode, widget.domNode);
    • A string with some widget ids which contains the widget appears in the StackContainer
  • Create a "dijit/layout/ContentPane", add it to StackContainer, assign widget.container=contentPane.id and than call widget.render();
    • A string with some widget ids which contains the widget appears in the StackContainer
  • Wait for rendering with "dojo/aspect" function after.
    • domNode ist still undefined
  • Watching for changes of domNode and/or container
    • Callback function doesn't call

Is there a way to solve this problem? How can I render a widget without an existing container? There have to be a solution but I haven't any idea. Can you help me out please? Any help is appreciated! Thanks!

Regards

Martin

0 Kudos
4 Replies
JohnGrayson
Esri Regular Contributor

Are you using the 'container' property when instantiating your widget?

Widget | API Reference | ArcGIS API for JavaScript 4.2  

In the app that consumes my widget, I normally create a dom node where I'd like my widget to be located then pass it in as the 'container' property when creating my widget instance, just like any of the other default widgets.  If adding to the View.ui, I normally just skip setting the 'container' property altogether.  If you need access to the 'real' node, you can use 'afterCreate' in your 'render()' method, something kind of like this:

render(){
  return (
    <div bind={this} class={CSS.base} afterCreate={this._initialze}></div>
  );
}

private _initialize(node: Element): void{
  /* do something with node here */
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

In your case, one of several options is to first create a ContentPane inside of the StackContainer, then create a dom node inside of the ContentPane and pass it into your widget as the 'container' property.  

deleted-user-iPdcWUgWcsoy
New Contributor III

Thank you for your reply. I tried your last option of creating the ContentPane, add it to StackContainer and use the automatically created domNode of ContentPane as the 'container' property. Unfortunately the result is just like the same as before. I get a string representation of a widget (currently inherited from "esri/widgets/Widgette") which are inside my custom widget. Am I missing something? Here is my code snippet. This is a module that handles adding and removing to and from the StackContainer.

// some code before...

// 1. Create the Helper-ContentPane.
var content = new ContentPane();

// 2. Add it to StackContainer and select it (this.navigationStack is type StackContainer).
this.navigationStack.addChild(content);
this.navigationStack.selectChild(content);

// 3. Just check id and domNode property.
console.info("content.id", content.id);
console.info("content.domNode", content.domNode);

// 4. Set container property as domNode of ContentPane.
component.container = content.domNode;

// ...some code after‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The result is this.

I debugged the widget handling and saw that this is the result of some core inheritance from dijit/_WidgetBase (toString function) which is used in esri/widgets/libs/maquette/maquette.js if there is no property 'vnodeSelector' while appending children in this custom widget. Here is the snippet of this part.

let toTextVNode = (data: any): VNode => {
  return {
    vnodeSelector: '',
    properties: undefined,
    children: undefined,
    text: data.toString(),
    domNode: null
  };
};

let appendChildren = function(parentSelector: string, insertions: any[], main: VNode[]) {
  for (let i = 0, length = insertions.length; i < length; i++) {
    let item = insertions[i];
    if (Array.isArray(item)) {
      appendChildren(parentSelector, item, main);
    } else {
      if (item !== null && item !== undefined) {
        if (!item.hasOwnProperty('vnodeSelector')) {
          item = toTextVNode(item);
        }
        main.push(item);
      }
    }
  }
};‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

So we use a custom main Widget with "esri/widgets/Widget" which contains one or more widgets inherited from "esri/widgets/Widgette". I know, the mixture of Widget and Widgette is not a nice solution but for some issues till now we have to use this base module and want to migrate later to esri/widgets/Widget.

Are there any other solutions or hints?

0 Kudos
JohnGrayson
Esri Regular Contributor

I'd use the 'containerNode' (not 'domNode'), or create a new node in the 'containerNode'. I set the 'container' property when creating the widget, not after. I don't recall any of the samples using 'esri/widgets/Widgette' (can't even find doc on it) and I've never used it; I've used 'esri/widgets/Widget', just like the samples.  I would suggest you start with a very simple widget, or use of of the provided samples, so you can work out the ContentPane/StackContainer issues first.

deleted-user-iPdcWUgWcsoy
New Contributor III

Thanks again for your reply.

 

The main problem is, that we just startet an implementation of a web app with about 40 or 50 widgets with 4.0 beta. At this beginning we used "esri/widgets/Widget"! But this base class had such big changes with 4.2 that we can't use it at this moment. Till 4.1 we could handle the new changes somehow. The migration will cost too much time. I think for this reason the module "esri/widgets/Widgette" was introduced for migration issues.

 

I see that there is no option to merge these two base widget modules. So we have to migrate. odoe it would be nice that "esri/widgets/Widgette" can be kept in the next one or two releases. That will give us the time to migrate all widgets. Is it possible? Thanks in advance.

0 Kudos