Ext.Create returning classes that are already instantiated - extjs4

I'm making use of the extjs class objects through Ext.define (... and Ext.create (.... When I have multiple instances of classes stored within another class I'm seeing some strange behavior: the classes are not unique and it looks like Ext.create is returning my previous instantiation.
Checkout the JSFiddle of my problem here. Make sure you view the console log in your browser to see the output and weirdness.

You're setting an array in Ext.define. That implies that you're setting into the object's prototype which is shared among all instances of a class. Therefore this is not an unexpected behaviour. Create the array within the constructor, like here:
Ext.define ('Sunglasses', {
brand : '',
constructor : function (args) {
this.lenses = [];
this.brand = args.brand;
},
addLenses : function (lenses) {
this.lenses.push (lenses);
}
});

Related

Dojo2: How to get the child widget instance to call functions on it

The setup is really simple, assume this piece of code:
export default class App extends WidgetBase {
protected render() {
return v('div', [
w(MyCustomWidget, {}),
v('button', {
id: 'abc',
classes: ['btn', 'btn-primary'],
onclick: this.clickMe
}, [
'Hello World!'
])
]);
}
}
The class MyCustomWidget defines now a function which I want to call from the current App-widget. If I do let cw = w(MyCustomWidget, {}) I get an object with the key instance which contains exactly what I want. But if I use cw.instace TypeScript tells me, that Property instance does not exist on type 'WNode<MyCustomWidget>'.
So how to do it properly?
I reached out to the guys from Dojo2 and they responded to me very quickly with:
If you want a child widget to call a function from the parent you need pass it to the child as a property. In dojo the widget instance are never exposed.
This was also my workaround but I was not sure if this was the correct way to do it. It certainly works. Now we know.

Recommended pattern for setting initialization parameters to custom widget

I'm creating my own template based widgets and I was trying to pass some objects through the constructor on creation like this
var widget = new myWidget(obj1, obj2, obj3);
where my constructor of the widget looks like
constructor: function(param1, param2, param3)
However I was getting some errors and found they were due to _WidgetBase functionality (specifically the create method) that is expecting something special in the first and second parameters.
create: function(params, srcNodeRef)
So in order to avoid my parameters nuking the params, and srcNodeRef that was expected in position one and two, I had to move my parameters to after the second position like this
constructor: function (params, srcNodeRef, myParam1, myparam2, myParam3)
But naturally this is not an expected way to solve this compared to the usual way to instantiate objects in normal object oriented languages (ex. c#)
My question is, is there a recommended pattern for passing initialization parameters to a custom widgets constructor, that avoids this issue of having to remember the first and second parameter positions are reserved?
NOTE:
An important note is that whatever parameters I send into the widget, must be acted on or made available before postCreate executes, just like it is if I passed them to the constructor.
Actually, there is a "dojo" way to pass parameters into your widget:
var widget = new myWidget({obj1: obj1, obj2: obj2});
In instance of your widget these object will refer to
this.obj1, this.obj2. You don't have to override constructor.
Some comments from dojo source of _WidgetBase on this topic:
//////////// INITIALIZATION METHODS ///////////////////////////////////////
/*=====
constructor: function(params, srcNodeRef){
// summary:
// Create the widget.
// params: Object|null
// Hash of initialization parameters for widget, including scalar values (like title, duration etc.)
// and functions, typically callbacks like onClick.
// The hash can contain any of the widget's properties, excluding read-only properties.
// srcNodeRef: DOMNode|String?
// If a srcNodeRef (DOM node) is specified:
//
// - use srcNodeRef.innerHTML as my contents
// - if this is a behavioral widget then apply behavior to that srcNodeRef
// - otherwise, replace srcNodeRef with my generated DOM tree
},
=====*/
I +1'd Kirill's answer as that's the easiest. But from the other comments it sounds like you might need to massage the input or initialize other variables based on the input.
If so, take a look at the postMixinProperties lifecycle method and override it in your widget. If your widget is templated and the template expects the massaged data, you'll need this. In here you refer to your properties with this as you expect.
postMixInProperties: function(){
// summary:
// Called after the parameters to the widget have been read-in,
// but before the widget template is instantiated. Especially
// useful to set properties that are referenced in the widget
// template.
// tags:
// protected
},
Don't forget to invoke this.inherited(arguments); in here as you should in all of the dijit lifecycle methods.
Defining setters for you properties is another way to massage these properties. You'll want this if a template will use these properties. Example of a setter from the Writing Widgets page. So here 'open' would be the name of the parameter as passed to the contructor, or in a widget template.
_setOpenAttr: function(/*Boolean*/ open){
this._set("open", open);
domStyle.set(this.domNode, "display", open ? "block" : "none");
}

how uses "uses" attribute in Ext.define?

How use "uses" attribute in Ext.define ?
Please example
I could find on the topic only Sencha Ext.define Uses vs Requires
Ext.define('Mother', {
uses: ['Child'],
giveBirth: function() {
// This code might, or might not work:
// return new Child();
// Instead use Ext.create() to load the class at the spot if not loaded already:
return Ext.create('Child');
}
});
List of optional classes to load together with this class. These aren't neccessarily loaded before this class is created, but are guaranteed to be available before Ext.onReady listeners are invoked.

Typescript error when using interface from module as field within class

I am working on providing a type definition file for fabric.js. The general structure is shown in the following sample:
declare module fabric {
export interface Canvas {
selectionBorderColor: string;
selectionColor: string;
...
}
var Canvas: {
new (): Canvas;
}
}
This pattern allows me to use fabric.Canvas in a 'interface-like' way, so that variables are associated with the fabric.Canvas interface. At the same time it allows me to call "static members" (such as the constructor of fabric.Canvas).
But this leads to a problem when using a field of interface 'fabric.Canvas' within a class. The following sample shows such an case:
This problem only occurs when placing the interface within a module, otherwise everything works fine.
Any solutions for this problem?
There is some type confusion because you have an interface and a field with the same name - I know this is common in the lib.d.ts file, but I don't think it is a good practice when writing new TypeScript code. It seems to be something of a necessity for defining existing code.
If you rename var Canvas to var MyCanvas (or anything else) your code works.
I tend to prefix my interfaces with an I, for example ICanvas - but this isn't a TypeScript convention (yet).
declare module fabric {
export class Canvas {
selectionBorderColor: string;
selectionColor: string;
}
}
class MyClass {
canvas: fabric.Canvas;
}

Using dojo.require() without dojo.declare()

I'm quite confused from Dojo's documentation. How can I use dojo.require() without actually using dojo.declare()? The reason I don't want to use dojo.declare() is that it exposes declared class as global variable.
Right now my code looks like this:
HTML file:
dojo.require('module.test');
Module/test.js:
dojo.provide('module.test');
function test() {
return 'found me';
}
I just can't get Dojo to return test() method anywhere. What's the correct pattern for using dojo.require() without declaring?
I think you are confusing dojo.provide/dojo.require with dojo.declare. They are completely different concepts.
Things that relate to modules
dojo.provide defines a module.
dojo.require requires that a module be defined before running any code later.
Things that relate to JavaScript classes
dojo.declare is something completely different. It declares a Dojo-style class.
You can have multiple classes in a module, or several modules making up one class. In general, modules !== classes and they are completely unrelated concepts.
dojo.provide defines the code module so that the loader will see it and creates an object from the global namespace by that name. From that point, you can anchor code directly to that global variable, e.g.
Module/test.js:
dojo.provide('module.test');
module.test.myFunc = function() {
return 'found me';
}
There are various patterns you can use, such as creating a closure and hiding "private" function implementations, exposing them via the global reference you created in dojo.provide:
dojo.provide('module.test');
function(){
// closure to keep top-level definitions out of the global scope
var myString = 'found me';
function privateHelper() {
return myString;
}
module.test.myFunc = function() {
return privateHelper();
}
}();
Note that the above simply puts methods directly on an object. Now, there's also dojo.declare, which is often used with dojo.provide to create an object with prototypes and mixins so that you can create instances with the 'new' keyword with some inheritance, even simulating multiple inheritance vai mixins. This sort of OO abstraction is often overused. It does approximate the patterns required by languages like Java, so some folks are used to declaring objects for everything.
Note that as of Dojo 1.5, dojo.declare returns an object and does not necessarily need to declare anything in the global scope.
Here's a pattern I sometimes use (this would be the contents of test.js):
(function() {
var thisModule = dojo.provide("module.test");
dojo.mixin(thisModule, {
test: function() {
return "found me";
}
});
})();
Now you can reference module.test.test() in your HTML page.