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?
Announcement
Collapse
No announcement yet.
X
-
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:
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.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", ... });
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?
-
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
-
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
and then in the class,Code:var record = this.getSelectedRecord(); isc.CustomerSummary.create(record);
arguments.length returns zero. Is this methodology incorrect for passing data to the class's constructor?Code:isc.defineClass("CustomerSummary", "Window"); isc.CustomerSummary.addProperties({ initWidget : function () { this.Super("initWidget", arguments); isc.say(arguments.length); } })
Comment
-
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:
Then in any method on CustomerSummary you can refer to this.foo and get "bar" or this.zoo to get 5. Makes sense?Code:var record = {foo: "bar", zoo: 5}; isc.CustomerSummary.create(record);
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
-
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:
Then, in the child Window, data is applied directly to the class instance, so you can access it as: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()" });
And access object methods on the parent withCode:this.setTitle(this.DATA['CUSTOMER_NAME']);
Note that in this example this.parent is the Window that contains the button and this.parent.parent is the parent object instance.Code:this.parent.parent.orderLinesGrid.addData(record);
A assume this, or some approximation thereof, is a typical pattern for doing this?
Comment
Comment