Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    How to create multiple instances of a Window

    Let's say your application has an "Order" window that shows an order. How do you create multiple "Order" windows? Since all the layout items in the window have an ID that is, apparently, in the global namespace?

    #2
    Component IDs are optional, if you don't specify one, SmartClient will generate a unique ID. So that's one option. The other option is to template the ID based on the ID of the creating component. For example:

    Code:
    isc.defineClass("OrderWindow", "Window").addProperties({
        title: "Order",
        initWidget: function () {
            this.Super("initWidget", arguments);
            this.addItem(isc.DynamicForm.create({
                ID: this.getID()+"_form",
                fields: [...]
            }));
        }
    });
    
    isc.OrderWindow.create({
        ID: "productOrder",
        ...
    });
    
    isc.OrderWindow.create({
        ID: "itemOrder",
        ...
    });
    In the above example, the OrderWindow contains a DynamicForm, whose ID is derived from the ID of the OrderWindow. So at the end of execution of the above block, there will be two forms, productOrder_form and itemOrder_form that you can then reference from other code.

    Of course if you're not interested in having global handles to those forms, you can just leave the ID out of their creation block.

    Does this answer your question?

    Comment


      #3
      Actually, a more generally useful pattern is to create two-way pointers between the creating and created components. Check out these two examples for a sample:

      http://www.smartclient.com/#_Extending_Component.Reuse
      http://www.smartclient.com/#_Extending_Pattern.Reuse

      In both of these, the creating component passes a pointer to itself to the created component. This completely avoids the use of globals and is a cleaner approach.

      Comment


        #4
        Followup

        Yes, this is more like the pattern I was looking for. Exactly what I was doing in my own code until I discovered SmartClient. What I'm not getting to work is passing data through to the constructor. For example, in the caller
        Code:
        var record = this.getSelectedRecord();
        isc.CustomerSummary.create(record);
        and then in the class,
        Code:
        isc.defineClass("CustomerSummary", "Window");
        
        isc.CustomerSummary.addProperties({
        
            initWidget : function () {
                this.Super("initWidget", arguments);
        
                isc.say(arguments.length);
            }
        })
        arguments.length returns zero. Is this methodology incorrect for passing data to the class's constructor?

        Comment


          #5
          The properties on 'record' that you're passing through to create() actually get applied to the class instance directly. So, for example if you have:

          Code:
          var record = {foo: "bar", zoo: 5};
          isc.CustomerSummary.create(record);
          Then in any method on CustomerSummary you can refer to this.foo and get "bar" or this.zoo to get 5. Makes sense?

          At present, arguments passed to create() don't make it all the way to initWidget(), but this seems like a useful pattern, so it will be next release if SmartClient.

          Comment


            #6
            A nice pattern to use to pass parent data to child window

            So then here is what I've come up with as a pattern. It's common in my app to have a button or other control spawn a Window (a custom class as shown in the above examples' links) that need both data from, and a link to, it's parent. The launch button:
            Code:
            this.lookupProductButton = isc.IButton.create({
                   title:"Lookup Product",
                   parent: this,
            
                   spawnProductLookupWindow: function() {
                       var data = {
                           parent: this.parent,
                           DATA: this.parent.DATA
                       };
                       isc.ProductLookupWindow.create(data);
                   },
            
                   click:"this.spawnProductLookupWindow()"
            });
            Then, in the child Window, data is applied directly to the class instance, so you can access it as:
            Code:
            this.setTitle(this.DATA['CUSTOMER_NAME']);
            And access object methods on the parent with
            Code:
            this.parent.parent.orderLinesGrid.addData(record);
            Note that in this example this.parent is the Window that contains the button and this.parent.parent is the parent object instance.

            A assume this, or some approximation thereof, is a typical pattern for doing this?

            Comment


              #7
              That's accurate. To the extent that it becomes cumbersome, you can avoid the parent.parent.parent type of chaining by passing in a named reference to the top-level component or use a global reference.

              Comment

              Working...
              X