Ext.Template is not defined - javascript

I'm having trouble preparing my application for deployment. I'm using ext-dev.js and have a compnent with the following:
Ext.define(myNameSpace.myComponentName, {
requires: ['Ext.XTemplate'],
tpl: new Ext.XTemplate('someTemplate')
})
On application startup it gives an
Ext.XTemplate is not a constructor
Do you have a solution for this?

You cannot define Ext.XTemplate inline because it hasn't been retrieved from the server yet by the Ext.Loader which handles loading of dependencies. There are two solutions:
// If you really want to add it to the prototype, but adding objects to the
// prototype is usually a bad idea since they are shared by all instances
// In this case, it may be ok, since there isn't much you can change about a
// template after you create it
Ext.define('myNameSpace.myComponentName', {
requires: ['Ext.XTemplate'],
}, function() {
// This callback is for when all the dependencies are loaded
myNameSpace.myComponentName.prototype.tpl = new Ext.XTemplate('someTemplate')
});
// Or just define it in initComponent, since you shouldn't instantiate it
// until after Ext.onReady is called (which means all dependencies are loaded)
Ext.define('myNameSpace.myComponentName', {
requires: ['Ext.XTemplate'],
initComponent: function() {
this.tpl = new Ext.XTemplate('someTemplate');
this.callParent();
}
});
UPDATE I actually forgot to list another possibility that may work, that is, don't use new, use Ext.create('Ext.XTemplate', args)'. The problem with Ext.create is that it will block until Ext.XTemplate (and dependencies) is loaded. I would still go with one of two approaches mentioned at the top

Related

One view for 2 or more pages (backbone.js)

I have two pages. One of them is dashboard with a lot of functionality. The second page is shared dashboard - the simple version of the first page.
The dashboard contains the view of the database (it can contain much other info, but the problem with this one). You can click on the filter button and modal window will be opened. So, simple version of the dashboard doesn't have this possibility. I'd like to add it, but I don't want to copy+past code from the full version of the dashboard because the code of this part is about two thousand lines. I'll add some primitive code example:
DashboardView = SomeAnotherView.extend({
initialize: function() {...},
events: {...} // huge objects of jQuery events,
render: function () {...},
... // 2k lines of functions for events
});
How can I use this View on another page? I tried to call a function from this view:
DashboardView.prototype.filterClicked(event);
But in this case event.curentTarget is null (it is necessary for this function), I also tried to send "this" to get the context, but it was failed.
Is there a possibility in Backbone.js to use one View for 2+ pages without any huge copy/past code?
Ideally if you have a simple version and full version of a view, you should have a "base view" (simple one) and the full version should extend the base view.
It'll look something like:
var SimpleDashbard = Backbone.view.extend({});
var Dashboard = SimpleDashbard.extend({});
In this way Dashboard will have access to the methods from SimpleDashbard.
Your situation sounds like you need to use a method from extended view in base view. Which is not a good idea. Ideally if it's shared you should move it to the base view/extract it into a utility method or service, and of course this involve re-writing this method to be reusable
If you have views that share a large amount of functionality, you could consider using the same View type, but opening it up to some configuration when instancing. For example:
var DashboardView = Backbone.View.extend({
initialize: function(options) {
this.allowFunctionX = (options && options.allowFunctionX);
this.allowFunctionY = (options && options.allowFunctionY);
},
// etc
functionX: function() {
if (!this.allowFunctionX) { return; }
// do the function...
},
functionY: function() {
if (!this.allowFunctionY) { return; }
// do the function...
},
});
Then on one page:
var firstDashView = new DashboardView({allowFunctionX: true});
and on another page:
var secondDashView = new DashboardView({allowFunctionY: true});
This may become not worth it if the functionality diverges too much (and there are likely better ways to configure than passing in a long list of booleans!). If your requirements are significantly different on your two pages, I feel like duplicating the code they both need is not a major sin.

Mootools 1.6 Subclass initialize method is not called

I'm using mootools 1.6.
I based my code on their tutorial but when I try to run it, the initialize function of my subclass is not invoked. Instead, it goes directly to the parent class' initialize function.
I tried breakpointing inside the subclass initialize function but it really doesn't go there. In fact, my additional functions are also undefined. It's like only the functions of the parent class are created. :(
Here's my sample code:
parent.js
var Parent = new Class({
initialize: function(){
alert("parent");
},
...
});
child.js
var Child = new Class ( {
Extends: Parent,
initialize: function () {
this.parent();
alert("child");
},
... some additional functions
});
1.) Note that they are in different js files.
2.) These files are preloaded by cocos2d-js
...
"src/controllers/parent.js",
"src/controllers/child.js",
...
I was able to solve this issue. There's no issue with Mootools. It was how I used it. I'm posting it for people who might encounter the same issue.
I have 3 js files.
parent.js
child.js
orphan.js (calling it orphan hahaha)
These 3 files are added to project.json in that order. I'm not using orphan.js. I thought I already removed it from the list but I was wrong. :(
Inside orphan.js, is a class. This class uses the same name as the class inside child.js. It's empty and is just extending the parent. What happened was, it redefined the object since it's loaded after child.js.
I switched their order to see if it will use child.js declaration instead and indeed, it did. But that's not the solution. I just used it to prove that it was redefined. The solution was to remove that file from source / make sure no classes have the same name.
Whew. false alarm.

How to extend 'old style' dojox widgets?

I've already written my own dijit widgets, as well as extended the existing one. It's simply making new declare with extended widget as argument, and using the own one instead of extended one.
However, I have a problem with dojox/form/Uploader, because it's that 'old-style' widget using old-style syntax. Instead of using the object returned by require, one should use the global object:
require(['dojox/form/Uploader'], function(Uploader){
var u = new dojox.form.Uploader({})
u.startup()
})
So, if I want to extend that widget, and using the child 'class' instead of the original, how should I actually do that?
Another thing I don't fully understand is, why whe need to use that 'old-style' syntax for dojox/form/Uploader, because it's created with the same syntax as 'normal' widget:
return declare("dojox.form.Uploader", [Base, Button, HTML5, IFrame, Flash], {
I believe you can extend it just like a 'new style' (AMD) widget, i.e.:
require([
"dojo/_base/declare",
"dojox/form/Uploader"
], function(decl) {
var MyUploader = decl(dojox.form.Uploader, {
buildRendering: function() {
this.inherited(arguments);
this.domNode.appendChild(
document.createTextNode(" ← awesome"));
}
});
new MyUploader({}).placeAt("x").startup();
});
Or am I misunderstanding your question? The reason there are traces of the 'old style' syntax in Uploader (and some other widgets) is probably just because nobody has had the time to port it to the new style yet (so it was probably automatically "converted").
Edit: Actually, the Uploader returns a 'new style' object in addition to setting the dojox.form.Uploader global. So you can actually change the above example to:
require([
"dojo/_base/declare",
"dojox/form/Uploader"
], function(decl, Uploader) {
var MyUploader = decl(Uploader, {
....
since Uploader === dojox.form.Uploader here.

the best pattern to keep references to global collections in Backbone

I'm developing an application in Marionette, but the topic refers to raw Backbone as well.
In my app, I've got many collections. Among them, there are 3 important ones, that are used all over the application (e.g. user data, such as names, which is displayed in most of views). The main question is: what is the best way (a good pattern to follow) to keep references to collections in Backbone/Marionette? I came up with few ideas below:
should I attach them as attributes of the Application object? If so, I'd have to pass the reference to Application object to all views, then views to their subviews, subviews to subsubviews, etc. But this seems a lame and ugly design.
instead, I could pass each collection separately, but this seems even worse solution, because I can't predict which (sub)view will ever need a collection. Keeping those nested references in order would be much more difficult than passing the Application object which I can pass once, always.
the is also a possibility to import the Application as a singleton. I'm using requireJS, most of the modules return constructors now (constructors of views, models and collections). Now the app module returns Application constructor, but instead, it could return the Application object. Then if a view requires to display some data from the collections, it could just require the app module and that's all.
finally, basing on the previous point, I thought I could create a plain map of collections and make it a singleton just as before. This is only to disable all views to have access to Application object, which still seems a bad pattern.
Please, suggest what you think is the best (commentson points above are welcome as well). I just need a good design pattern here. As far as I know, Marionette docs doesn't suggest anything here.
I follow the suggestions made in David Sulc's book Backbone.Marionette.js: A Gentle Introduction. (also the next book on goes into how to then sturcutre the same project with require https://leanpub.com/structuring-backbone-with-requirejs-and-marionette)The code examples he uses are available on github so you could look at the final example which to get an idea of what he does if you didn;t want to buy the book but i really recommend it as it really helped me with how to structure my projects.
To start I have setup an Entities module. The structure of the files also follows this I have an Entities folder which has separate entities.
Each Entity file concerns all actions and stucture of that particular entity. I like this approach as I when i want to edit an entities strcuture or method of getting data from the server i only need to go to one place to make this change.
Interactions with entity are handled through marionettes req/res system. In this way you can expose a handler to the rest of your app but they don;t need to be concerned with how that req gets handled as long as it brings back the required response.
Here is an example of one of my entities to show what i mean - My app needs a collection called positions at various stages so this is something that is loaded early in the app then is available through-out it's life-cycle.
//i am using require so i define my app to use
define(["app", ], function(MyApp) {
//All of this will be added to the Entities module so if i want direct access
//i can go Myapp.Entities.whateverEntityIhaveDeclared
MyApp.module("Entities", function(Entities, MyApp, Backbone, Marionette, $, _) {
//model (nothing new here)
Entities.Position = Backbone.Model.extend({
urlRoot: "api/positions",
defaults: {
name: "",
}
});
//collection again nothing new here
Entities.PositionCollection = Backbone.Collection.extend({
url: "api/positions",
model: Entities.Position,
comparator: "name"
});
//an init function to attach a position collection onto Entities module so it can be available throughout my app
var initializePositions = function() {
if (Entities.positions === undefined) {
Entities.positions = new Entities.PositionCollection();
}
};
//
var API = {
//returns a jquery deferred promise so that this request can easily be handled async
loadPositionEntitiesRemote: function() {
//init positions make's sure i have the collectoin avaliable if it
//has not yet been defined
initializePositions();
//setup defer object
var defer = $.Deferred();
//I actually use a custom sever object here when dealing
//with ajax requests
//but because my app always go through this API i can
//easily swap out how the collection is retrieved.
// Here is an example using backbones fetch
Entities.positions.fetch({
success: function() {
defer.resolve();
},
error: function(data) {
defer.reject(data);
}
});
//setup promise to return
var promise = defer.promise();
return promise;
},
//get the positions collection from here i could
//directly access the attributes or add to the collection
refrencePositionEntities: function() {
initializePositions();
return Entities.positions;
},
//get a position from the collection based on id
//
getPositionEntity: function(positionId) {
initializePositions();
return Entities.positions.get(positionId);
}
};
//setup handlers for the app to use
MyApp.reqres.setHandler("position:entities:remote", function() {
return API.loadPositionEntitiesRemote();
});
MyApp.reqres.setHandler("position:entities:refrence", function() {
return API.refrencePositionEntities();
});
MyApp.reqres.setHandler("position:entity", function(id) {
return API.getPositionEntity(id);
});
MyApp.reqres.setHandler("position:entity:new", function(position) {
return new Entities.Position(position);
});
});
return;
});
now to use this in my app here is an example of how it can now be used
someFunction: function(){
//so early in the app i will get the positions
var positionPromise = MyApp.request("position:entities:remote");
$.when(positionPromise).done(function() {
//do what ever as data has been loaded
}).fail(function(data){
//something failed so handle here might through up an error page but up to you
}).always(function(){
//something to always do no matter if fail or sucess
});
}
anotherFunction: function(){
//later in the app in another controller i might to get the collection
// I could also get it through MyApp.Entities.positions but i rather use the
// API set up so if i ever decided i want to add so checks or something in
// when retrieving the collection its super easy
var positionsCollection = MyApp.request("position:entities:refrence");
}
Not sure if i've done a great job explaining this but if you are looking for a ideas on good design in marionette check out the book as it explains this a lot better than i have just done

Is there any standard practice when it comes to adding plugin into ExtJs 4.1 apps

I am going to add a plugin to my ExtJs 4.1 application. Currently I have added the code for plugin into one of the file where I am making use of the plugin and everything is working fine.
Alternatively I can put the plugin code in a JS file and then can make reference of the file in my application.
But I was wondering is there way to include the plugin without making explicit reference? Just like we load Controllers, store etc in ExtJs 4.1
There is no standard practice, but in my opinion it makes the most sense to define a namespace for plugins (e.g., App.plugin.MyPlugin) and load them either explicitly as needed, or along with your other required files if you're using the Ext.Loader.
Here is an example...
Ext.define("App.plugin.MyPlugin", {
/** Any explicit class properties and methods for functionality go here.
Eg. extending, aliasing, defining initComponent to add events, and
any other class-specific methods. */
},
function(){
Ext.ns("App.plugin");
App.plugin.MyPlugin = {}; // this is a global
var MyPlugin = App.plugin.MyPlugin;
/** You can modify the prototype here */
this.prototype.dateFormat = Ext.Date.dateFormat;
/** If you need to add functionality from some other class,
or Ext class, you can marge them here. In this example,
I am adding in the methods from Ext.util.Format */
Ext.apply(MyPlugin, Ext.util.Format);
/** Define methods which can be invoked from the global */
Ext.apply(MyPlugin, {
exampleRenderer: function(val){
return MyPlugin.ucfirst(val); // available via Ext.util.Format
}
});
});
Now you can instantiate the plugin class, but also access the global methods. For example, you can leverage the exampleRenderer in a gridcolumn renderer via App.plugin.MyPlugin.exampleRenderer.
To automatically load your plugin, you must define the path for the namespace in your `Loader' configuration. e.g.,
Ext.Loader.setConfig({
enabled: true,
paths : {
'App.plugin': '/js/app/plugin/' // or however your folder structure is
}
});
/** then require it.. */
Ext.require([
'App.plugin.MyPlugin'
]);
You likely do not want to combine the two principals into one class, but I just wanted to show a couple different means to achieve your goal.

Categories

Resources