how to define global variable in extjs 3.4 - extjs

I want to declare a global variable like var i=0; in extjs 3.4. in order to check the maximum occurences of '?' inside keypress listner. How can i do that.
Code:
keypress: function(combo, e) {
var i = 0;
var charCode = e.getCharCode();
if ( e.shiftKey && charCode === 63 ) {
i = i+1;
if(i=== 3){
alert('max three ?s allowed');
}
}
}
}
Here every time i is becoming zero so i want to declare i as global.
Raj

If you tend to use MVC structure for your application, simply define them in app.js
Note: To my experience, global variable should be meaningful and uppercase. For example:
var MY_GLOBAL_VARIABLE = some_value;

Using Global variable is Generally a bad idea.
If I were you I'd wrap up the variables I needed to share in a singleton.
PHP Code:
Ext.define('SaherdData', {
singleton: true,
txt: 'myvalue',
meh: 42
});

Related

Binding an integer to AngularJS 1.5 component

When using attribute binding in components, the data passed to the controller is always a string. I'm trying to pass an integer, however, and am having trouble converting it from a string and having the conversion stick.
I've tried saving the data as an integer in $onInit() but outside of this function, the data returns to its original state (type and value). I understand that components should not modify the data passed in as a general rule, but since this is an attribute binding, and the data is passed by value, I didn't think that applied.
function IntegerBindingController() {
this.$onInit = function() {
// Assuming 'number="2"' in the HTML
// This only changes the data inside this function
this.number = parseInt(this.number)
this.typeofNumber = typeof this.number // evaluates to 'number'
this.simpleAdd = this.number + 5 // evaluates to 7
this.dataAdd = this.numberOneWay + 5
console.log(this)
}
this.test = function() {
// this.number is a string inside this function
this.typeofNumber = typeof this.number // evaluates to 'string'
this.simpleAdd = this.number + 5 // evaluates to 25
}
}
I can solve this by copying the data to a new property on the controller, but I'm curious if someone can explain what's happening here. See this Plunker for a working example of the issue.
Passing number with '#' will always pass it as a string. If you want the object value pass number with '=' instead in the components bindings.
So:
var IntegerBindingComponent = {
controller: IntegerBindingController,
bindings: {
string: '#',
number: '=',
numberOneWay: '<'
},
template: _template
}
A decent explanation can be found here: http://onehungrymind.com/angularjs-sticky-notes-pt-2-isolated-scope/
or here: Need some examples of binding attributes in custom AngularJS tags
"The '=' notation basically provides a mechanism for passing an object into your directive. It always pulls this from the parent scope of the directive..."
The solution I ended up going with was to use $onChanges to handle the bound data values. In my case, at least one of the values could potentially change after an async call in the parent component, so this made sense overall. As Prinay Panday notes above, the # binding always comes through as a string. The $onInit() method guarantees that bindings will be available, but it doesn't guarantee that they will change, so even if you change the value on the component, Angular can change it later. That's another reason why the documentation recommends copying the bound values to a local variable if you need to manipulate them at all. As for the $onChanges() solution, it would look like this
function IntegerBindingController() {
this.$onChanges(changes) {
if (changes.number && changes.number.currentValue) {
this.number = parseInt(changes.number.currentValue)
}
}
this.test = function() {
this.typeofNumber = typeof this.number // evaluates to 'number'
this.simpleAdd = this.number + 5 // evaluates to 7 (assuming this.number was 2)
}
}

Detection of Index in Angular: indexOf() does not work properly because of $$hasKeys?

Following Situation:
role: { roleid=3, name="admin"}
availableRoles:
[
{ roleid=3, name="admin", $$hashKey="object:222"},
{ roleid=4, name="plain user", $$hashKey="object:223"}
]
currentRoles:
[
{ roleid=3, name="admin"}
]
Following Trys:
currentRoles.indexOf(role); // works properly and outputs 0
availableRoles.indexOf(role); // does not work
I can imagine, this occurs because of $$hasKeys. But I didn't put them there, AngularJS does augment these data.
How can I overcome this situation?
Is there a function like: ignore Angular HasKeys in this Datastructure?
Edit:
Angular object comparison:
Compare objects in Angular
So you can just write the function:
function arrayObjectIndexOf(arr, obj){
for(var i = 0; i < arr.length; i++){
if(angular.equals(arr[i], obj)){
return i;
}
};
return -1;
}
--ORIGINAL--
JavaScript saves objects as pointers, therefore, two objects even if has the same data in them, have different values (the value of the pointer in the memory).
Code example:
var role = { roleid:3, name:"admin"};
var availableRoles =
[
{ roleid:3, name:"admin"},
{ roleid:4, name:"plain user", $$hashKey:"object:223"}
];
alert(availableRoles.indexOf(role));
http://codepen.io/anon/pen/BjobaW
So it does not relate to the hashKey. To compare to objects (and such, find the index in an array) you must create a loop of comparison, or overload the "==" operator of Object to compare values and not pointers, which I dont believe you are allowed to do in JS.
Best way is not to have such objects...
You can use angular filter:
function contains(arr, id) {
return $filter('filter')(arr, {roleid : id}, true).length != 0;
}
You can use some other js library (lodash, underscore, ...) for such things.

Angular Translate - how to retrieve dynamic variable list

I have this in the translation json file:
{
"test_key" : "Var1: {{var1}} Var2: {{var2}} Var3: {{var3}}"
}
For this to work, I need to provide var1, var2, and var 3. For example:
$translate('test_key', { var1: 1, var2: 2, var3: 3 });
The issue now is that var1, var2, var3 could be any dynamic variables. What I need now is to get all the list of dynamic variables so I can provide whatever values it may need.
Ideally, this is the goal I am trying to achieve (pseudo code)
var dynamicVars = getDynamicVarList(); // I need this, but how?
dynamicVars.forEach(function (key) {
switch (key) {
case "var1":
return 1;
case "var2":
return 2;
case "var3":
return 3;
default:
return null;
}
});
If it is Pascal Precht translate, then you set JSON file in module options, before application init. It's rather not possible with standard mechanisms. It offer JSON, but when it is loaded, then it's hard to change something, without changing source code of angular translate module.
If the reason you want this is to have many languages, then you can set many languages codes in $translate.
Another solution is to load JSON from server, which performs operations on var1, var2, var3 and hence returns static json, but you can do $http calls with commands to change variables in switch statement.
It looks somehow linguistic approach, Java is good for this. Grails may be fine framework for returning REST services.
Again, to restate the problem, the issue is that you do not know ahead of time which dynamic variables are to be used.
I solved the issue by using a customer interpolator.
So when you do
{{'testkey'|translate}}
and your lang.json has:
"testkey" :"this is number {{variable1}}"
It will get resolved to
this is number 1
Code:
app.factory('customTranslateInterpolator',
["$interpolate",
function ($interpolate) {
var $locale;
var customTranslateInterpolator = {};
/**
* This will be your custom dynamic vars resolution method
*/
var resolveExpressions = function (expressions) {
var values = {};
expressions.forEach(function (key) {
values[key] = resolveVariable(key);
});
return values;
}
/**
* The actual method for key:value mapping
*/
var resolveVariable = function(key) {
var retVal;
switch (key) {
case "variable1":
retVal = 1;
break;
default:
retVal = "";
}
return retVal;
}
customTranslateInterpolator.setLocale = function (locale) {
$locale = locale;
}
customTranslateInterpolator.getInterpolationIdentifier = function () {
return 'custom';
},
/**
* Custom interpolate
* interpolateParams will overwrite resolve expressions. This will allow developers
* to pass values to the translate directives or by using $translate service.
*
* #param {string} string the string retrieved from the language json file
* #param {object} interpolateParams the {key:value} object passed to the angular-translate features.
*/
customTranslateInterpolator.interpolate = function (string, interpolateParams) {
var result;
interpolateParams = interpolateParams || {
};
// Retrieve expressions and resolve them
var interpolatedString = $interpolate(string);
var resolvedExpressions = resolveExpressions(interpolatedString.expressions);
// Merge interpolateParams onto resolvedExpressions so that interpolateParams overwrites resolvedExpressions
angular.extend(resolvedExpressions, interpolateParams);
result = interpolatedString(resolvedExpressions);
return result;
}
return customTranslateInterpolator;
}]);
make sure you let angular-translate know you are using a custom interpolator
$translateProvider.useInterpolation('customTranslateInterpolator');
Note that you can still provide your own translate-values, and this will override whatever you have in resolveVariable()
So if you do
{{'testkey' | translate:"{variable1:'2'}"}}
It will resolve to
this is number 2
Hope this helps others.
-Lucky M.

Compare getValue with map.layers[i].name

As part of a xtype combo, I would like to know if the layer I choose in my simple data store (represented by this.getValue()) is present in the map layers. So if it does, A should occur, and B if it does not. The problem is that myLayer variable seems to be unrecognized, even though Opera Dragonify throws no error at all. Where would be the error?
listeners: {
'select': function(combo, record) {
for(var i = 0; i < mapPanel.map.length; i++) {
var myLayer = mapPanel.map.layers[i].name;
if (myLayer == this.getValue()) {
// do A here...
} else {
// do B here...
}
}
}
}
Thanks for any pointers,
I think the problem is that you are using this.getValue() instead of using combo.getValue().
I don't know how your app is set but it's usually a better idea to use the first parameter of your listener instead of the keywork this in order to avoid scope issues.
Hope this helps
#Guilherme Lopes Thanks for that, but the solution was this: mapPanel.map.layers.length instead of mapPanel.map.length.

$location partial path change

If there is s path of /#/var1/oneVariable/var2/many,more,variables/var3/last,set and I wanted to update the $location, is there a way to only update the variable part of the path without having to re-declare everything from the current path?
Is something like this possible?:
$location.path(var2 = 'changed,all,three';)
and having the result be /#/var1/oneVariable/var2/changed,all,three/var3/last,set
I don't think that it is possible by default. However, you can create a function by yourself that keeps track of the current variables and fills them in for you when you need to change one of them and calls $location.path().
var currentParams = {
var1: 'oneVariable',
var2: 'many,more,variables',
var3: 'last,set'
};
function changePath(params) {
angular.forEach(params, function (value, key) {
currentParams[key] = value;
});
$location.path('/var1/'+ currentParams.var1 + '/var2/' + currentParams.var2 + '/var3/' + currentParams.var3);
}
You can call it now by using changePath({var2: 'changed,all,three'}).
Note that this is a simplified example. You can make it more flexible and it would be good to put it into an Angular service.

Resources