Defining a namespace with ExtJs5 - extjs

I'm using ExtJs 5 and SenchaCmd.
In a package, I defined several classes in several files like this:
// Bar1.js
Ext.define('Foo.Bar1', {
...
});
// Bar2.js
Ext.define('Foo.Bar2', {
...
});
Now I'd like to just "augment" the Foo namespace with some general tools like this :
Ext.ns('Foo');
Foo.tool1 = function() { ... }
Foo.tool2 = function() { .... }
Foo.generalProp1 = 42;
(...)
What would be the better place and practive to declare this so that the Sencha Compiler embeds this file too?
Is it possible to "require" (in a way) a namespace like we require a class?

You can use statics from new Ext:
Ext.define('Foo', {
// declare static members
statics: {
method: function(){ return "static method"; }
}
});
// Define class under Foo namespace
Ext.define('Foo.OtherClass', {
method: function(){ return "instance method"; }
});
// Create instance of Foo.OtherClass
var o = Ext.create('Foo.OtherClass');
// Use static member
console.log(Foo.method());
// Use instance member
console.log(o.method());
Then you can treat your Foo namespace like class, and place as any other class.
Then obviously you can also require that namespace, because it is also class.

Related

Access static members in mixins

The instruction this.constructor doesn't work in mixins. I get an undefined value. I wonder why it happens and is it possible to use this instruction. There is a code example:
qx.Mixin.define("MZoomable", {
statics: {
MAX_ZOOM: 500
},
members: {
printMaxZoom: function(){
alert(this.constructor.MAX_ZOOM);
}
}
});
qx.Class.define("MyClass", {
extend: qx.core.Object,
include: [MZoomable],
constuct: function(){
this.base(arguments);
}
});
const o = new MyClass();
o.printMaxZoom();
alert in printMaxZoom will show undefined word.
The answer is that this.constructor refers to the class of the object at runtime, and that would be MyClass. I would expect that if you modified printMaxZoom to be:
printMaxZoom: function(){
alert(this.constructor === MyClass);
}
Then you would get an alert that says "true".
This is an inherent characteristic an environment where the type is determined (including the addition of a mixin) at runtime.
If you want to refer to static members of a Mixin, you should use the absolute syntax, eg:
printMaxZoom: function(){
alert(MZoomable.MAX_ZOOM);
}
Note that it is always good practice to use the absolute path for static variables, and it is often a bug to use this.constructor as a shortcut.
For example:
qx.Class.define("MyClassOne", {
extend: qx.core.Object,
construct: function(){
this.base(arguments);
alert(this.constructor.MY_VALUE);
},
statics: {
MY_VALUE: 23
}
});
qx.Class.define("MyClassTwo", {
extend: MyClassOne
});
// creates an alert that says "23"
var one = new MyClassOne();
// creates an alert that says "undefined"
var one = new MyClassTwo();
The issue is the same as the one in your question, in that this.constructor is the actual class of the object, and not the class (or mixin) where the this.constructor statement appears.

Angular and Typescript: proper way to reference 'this'

I am setting typescript in an angular project. In order to declare a controller I use the following syntax:
module app {
class MyController {
public myvar: boolean;
constructor() {
this.myvar= false;
}
}
angular.module("app").controller("MainController", [MainController]);
}
Please note that I don't inject the scope, I only use inner properties / methods of the controller.
But I don't like to access to properties with 'this', usually I should declare:
var vm = this.
vm.myvar = ...
However this is annoying as I have many methods; I should declare this in any ones, this is repetitive.
Is there a best practice and/or a pattern, in order to declare the 'vm' only once?
But I don't like to access to properties with 'this', usually I should declare var vm = this ... Is there a best practice and/or a pattern, in order to declare the 'vm' only once?
It's a good time to drop that practice. In TypeScript it's easy to just use this and not assign this to a variable—it's already defined for you so it's nice to use it.
The key when doing this is to use arrow functions to make sure you always use the class instance's this and not the this bound to a regular function expression.
class MyController {
myVar = false;
someOtherMethod() {
// good
functionWithCallback(() => {
// this will be the class instance
console.log(this.myVar);
});
// bad
functionWithCallback(function() {
// this will not be the class instance
console.log(this.myVar);
});
// good
functionWithCallback(() => this.myOtherMethod());
// bad, `this` in myOtherMethod is not the class instance
functionWithCallback(this.myOtherMethod);
}
myOtherMethod() {
console.log(this.myVar);
}
}
function functionWithCallback(callback: Function) {
callback();
}

Creating a custom Angular filter with TypeScript

I'm trying to work out the best way of creating a custom Angular Filter with TypeScript.
All the code samples I see use something like:
myModule.filter( "myFilter", function()
{
return function( input )
{
// filter stuff here
return result;
}
}
... which works, but seems messy as I want to keep all my filter code separate. So I want to know how to declare the filter as a separate file (eg filters/reverse-filter.ts) so I can create it like:
myModule.filter( "filterName", moduleName.myFilter );
... the same way you would for Controllers, Services etc.
The documentation for TS and Angular together seems pretty thin on the ground, especially where filters are concerned - can anyone help out?
Cheers!
Functions can be exported from modules like this:
module moduleName {
export function myFilter()
{
return function(input)
{
// filter stuff here
return result;
}
}
}
then outside the module:
myModule.filter("filterName", moduleName.myFilter);
Then it would then be possible to do things like automatically register all of the filters defined in the moduleName module by iterating over its public properties.
Maybe too late but can be useful for someone else.
module dashboard.filters{
export class TrustResource{
static $inject:string[] = ['$sce'];
static filter($sce:ng.ISCEService){
return (value)=> {
return $sce.trustAsResourceUrl(value)
};
}
}
}
dashboard.Bootstrap.angular.filter('trustAsResourceUrl',dashboard.filters.TrustResource.filter);
To explain the last line:
dashboard.Bootstrap.angular.filter('trustAsResourceUrl',dashboard.filters.TrustResource.filter);)
I will add a piece of code, wich represents my Bootstrap class, so you can understand it.
module dashboard {
export class Bootstrap {
static angular:ng.IModule;
static start(){
Bootstrap.angular = angular.module('EmbApp', dashboard.Bootstrap.$inject);
}
}
}
//run application
dashboard.Bootstrap.start();
If you need more information about how it works, you can checkout my own TypeScript/AngularJS/Less structure here
Here's an example using the injector to get dependencies into your filter. This one gets injected with the $filter service.
export class CustomDateFilter {
public static Factory() {
var factoryFunction = ($filter: ng.IFilterService) => {
var angularDateFilter = $filter('date');
return (theDate: string) => {
return angularDateFilter(theDate, "yyyy MM dd - hh:mm a");
};
};
factoryFunction.$inject = ['$filter'];
return factoryFunction;
}
}
// and in the bootstrap code:
app.filter('customDate', your.module.CustomDateFilter.Factory());
You should use something like this to inject dependencies
myModule.filter('filterName', ['$http', moduleName.myFilter]);
You can create a filter using class with a static function.
export class FilterClass
{
static id = "FilterId"; //FilterName, use while consume
/*#ngInject*/
public static instance() { //static instance function
let dataFilter = () => {
let filteredObject = () => {
//filter logic
return filteredData;
}
return filteredObject;
}
return dataFilter;
}
}
//Module configuration
angular.module(myModule).filter(FilterClass.id, FilterClass.instance());
Consume this filter in the controller using below way.
let FilterFun:any = this.$filter('FilterId');
let Filteroutput = FilterFun();

Backbone Boilerplate Layout Manager

Can someone help explain / provide an example on how to use the LayoutManager within the Backbone Bolierplate?
Within app.js I can see a useLayout function that extends the main app object. Within here it appears to be setting a base layout element:
// Helper for using layouts.
useLayout: function(name, options) {
// Enable variable arity by allowing the first argument to be the options
// object and omitting the name argument.
if (_.isObject(name)) {
options = name;
}
// Ensure options is an object.
options = options || {};
// If a name property was specified use that as the template.
if (_.isString(name)) {
options.template = name;
}
// Create a new Layout with options.
var layout = new Backbone.Layout(_.extend({
el: "#main"
}, options));
// Cache the refererence.
return this.layout = layout;
}
Is that correct? If so, do I somehow the use the 'UseLayout' function with the applications Router? ...to add different UI elements/nested views to the main view?
Thanks.
I will usually have an "app" object that stores all my settings needed throughout the application. This object then extends some useful functions like the one you listed above. For example:
var app = {
// The root path to run the application.
root: "/",
anotherGlobalValue: "something",
apiUrl: "http://some.url"
};
// Mix Backbone.Events, modules, and layout management into the app object.
return _.extend(app, {
// Create a custom object with a nested Views object.
module: function(additionalProps) {
return _.extend({ Views: {} }, additionalProps);
},
// Helper for using layouts.
useLayout: function(options) {
// Create a new Layout with options.
var layout = new Backbone.Layout(_.extend({
el: "#main"
}, options));
return this.layout = layout;
},
// Helper for using form layouts.
anotherUsefulFunction: function(options) {
// Something useful
}
}, Backbone.Events);
});
Now in my router I would do something like:
app.useLayout({ template: "layout/home" })
.setViews({
".promotional-items": new Promotions.Views.PromotionNavigation(),
".featured-container": new Media.Views.FeaturedSlider({
vehicles: app.vehicles,
collection: featuredCollection
})
}).render().then(function() {
//Do something once the layout has rendered.
});
I have just taken a sample from one of my applications, but I am sure you can get the idea. My main layout is basically just a layout template file which holds the elements so the views can be injected into their respective holders.
You would use it as if you're using a regular Backbone View. Instead of building the View directly, you can use this to create a new instance. The code you posted is a wrapper object on top of the Backbone Layout Manager extension with el: #main set as the default View element which is overridable.
var layout = new useLayout({ template: "#viewElement", ... });

Extjs Class System statics

I want to define a class with utility functions. I'm using Extjs class system.
I'm doing this in the following way:
Ext.ns('Controls.Plugins.Nzok')
Ext.define('Controls.Plugins.Nzok.XUtility', {
statics : {
getTest : function(test) { return test }
}
})
Now when I want to use getTest method I have to require the class and to write full class name
Ext.define('Controls.Plugins.Nzok', {
requires : ['Controls.Plugins.Nzok.XUtility'],
useTest : function() {
var testResult = Controls.Plugins.Nzok.XUtility.getTest(2);
}
})
My problem is that notation is too long. It's very inconvenient to write down every time Controls.Plugins.Nzok.XUtility. Are there any solution?
The alternateClassName config does the trick.
Ext.define('Controls.Plugins.Nzok.XUtility', {
alternateClassName: 'Controls.XUtil', // <--- this is your shorthand
statics : {
getTest : function(test) { return test }
}
});
As a side note, Ext.define will automatically create namespaces based on your class name, so Ext.define('Controls.Plugins.Nzok.XUtility' will generate the Controls.Plugins.Nzok namespace for you.

Resources