AngularJS $parse/scope.$eval expression - angularjs

I am trying to use $parse to get my required result.
Here is my Example. Check script.js file
I want to parse an expression but I am getting error. How can I solve this kind of data?
Here is my code
scope.data = {name:{_en:"username", _ar:'مفقود '}}
// set variable in scope like scope.name_en = scope.data._en, scope.name_ar = scope.data._ar
for(var i in scope.data) for(var j in scope.data[i]) scope[i+j] = scope.data[i][j];
scope.messages2 = [{code:200, msg_en:"{{name_en}} is missing.", msg_ar:"مفقود {{name_ar}}"}];
scope.finalMegs = [];
for( var i in scope.messages2) {
var obj = {};
for(var j in scope.messages2[i]){
if(j == 'code') continue;
console.log(scope.$eval(scope.messages2[i][j]) );
obj[j] = $parse(scope.messages2[i][j])
}
/*
required object is {msg_en = "username is missing.", msg_ar:"مفقود مفقود "}
*/
scope.finalMegs.push(obj);
}
console.log(scope.finalMegs);
Thank you.

Syntax of your messages is incorrect, so the messages can't be parsed by $parse or $eval. You should write them in this format:
scope.messages2 = [
{
code:200,
msg_en:"name_en + ' is missing.'",
msg_ar:"'مفقود ' + name_ar"
}
];
Then if you want to get object with already formatted messages you should call $parse function in this way:
obj[j] = $parse(scope.messages2[i][j])(scope);
Because $parse converts angular expression to function, which you should call with your scope to get expected results.
But in your case, I think that you can replace those line to this also:
obj[j] = scope.$eval(scope.messages2[i][j]);
Result will be the same.
Example on plunker. (I've reformatted your example a little bit)
Please, take a look also at the example of usage scope.$eval here and documentation about $parse.

Related

Reference Error when dynamically creating variables with eval() in Angular

I am trying to create dynamically generated variables based on another variable, such as:
var limit = 2;
$scope.blank_item = [];
$scope.create_vars = function(limit){
for(i=0; i<limit; i++){
eval('var item' + i) = $scope.blank_item;
};
};
And this should give me 3 new variables like below:
var item0 = [];
var item1 = [];
var item2 = [];
However, when I try to do this, I get the following error message:
ReferenceError: Invalid left-hand side in assignment
Is there something fundamentally wrong with my logic?
This has nothing to do with Angular. The value passed to eval() has to be one or more statements, not part of a statement. And you certainly can't pass part of a statement to eval() and then assign a value to it.
Even you could do that, it would just be creating temporary variables that disappeared as soon as your function finished executing.
Ditch the eval() and use an array:
var limit = 2;
var items = [];
$scope.blank_item = [];
$scope.create_vars = function(limit){
for(i=0; i<limit; i++){
items[i] = [];
};
};

What is the best effective way to collect data from a table using protractor?

What is the best effective way to collect data from a table using protractor.
I collecting the data shown in the code below and it is taking 20-30 seconds for 10 rows.
The buildStr counter is for creating a object for every row, 8 is the number of columns.
row = {};
gridRows = [];
element.all(by.css('#contenttableGrid div[role="gridcell"] div')).each(function(element){
element.getText().then(function(text){
row[headerName[buildStr]] = text;
buildStr++;
if(buildStr === 8){
buildStr = 0;
gridRows[rowCounter] = row;
rowCounter++;
row = {};
}
});
});
One way to speed it up that I see is to extract all the data right on the page by injecting script on it. It could be done with the help of browser.executeScript() (docs). In your sample Protractor has to make a request to the browser any time you call getText(), nubmer of calls it makes = number of cells in your table. But using browser.executeScript() it will make one call and do all the stuff in the browser, which can be really fast. Then you can simply return this data back to a test spec and use it via Promises.
var headerName = {};
// I assume that this variable holds names for headers
// you can pass data from test spec to injected script as arguments (below)
// promise will be resolved with the value you return from `executeScript`
var promise = browser.executeScript(function (headerName) {
// all the stuff inside this function happens on your page under test
// it is not a Protractor environment
var buildStr = 0;
var rowCounter = 0;
var row = {};
var gridRows = [];
var cells = document.querySelectorAll('#contenttableGrid div[role="gridcell"] div');
for (var i = 0, l = cells.length; i < l; i++) {
var text = cells[i].textContent;
// `headerName` object is passed as an argument from test spec
row[headerName[buildStr]] = text;
buildStr++;
if (buildStr === 8) {
buildStr = 0;
gridRows[rowCounter] = row;
rowCounter++;
row = {};
}
}
// return all collected data back to test spec
return gridRows;
}, headerName); // pass helper object from test spec to injectable function
promise.then(function (gridData) {
console.log(gridData); // result of computations
});
Make sure to read docs for browser.executeScript() if you want to use it, because it has a lot of specific moments.

substring from an array as3 **Error #1009: Cannot access a property or method of a null object reference

I am trying to create a matching game where one object in the array hitBoxes is matched to one object in the array hitBoxes2. I have tried to convert the instance name into a string and then used the substring method to match the LAST number in the instance name, if its a match they win. Right now I'm getting the error
TypeError: Error #1009: Cannot access a property or method of a null
object reference. at MethodInfo-499()
I'm wondering if anyone can help me. Thanks!
var left:String;
var correct:MovieClip = new Correct;
var isClicked:Boolean = false;
var leftClicked:int = 0;
p3.nextPage.buttonMode = true;
p3.nextPage.addEventListener(MouseEvent.CLICK, nextPage);
function nextPage(MouseEvent):void{
removeChild(p3);
}
var hitBoxes:Array = [p3.a1, p3.a2, p3.a3, p3.a4, p3.a5, p3.a6, p3.a7, p3.a8];
var hitBoxes2:Array = [p3.b1, p3.b2, p3.b3, p3.b4, p3.b5, p3.b6, p3.b7, p3.b8];
for (var h:int = 0; h < hitBoxes.length; h++){
hitBoxes[h].buttonMode = true;
hitBoxes[h].addEventListener(MouseEvent.CLICK, matchingLeft);
}
for (var h2:int = 0; h2 < hitBoxes2.length; h2++){
hitBoxes2[h2].buttonMode = true;
hitBoxes2[h2].addEventListener(MouseEvent.CLICK, matchingRight);
}
function matchingLeft(e:MouseEvent):void{
var left = String(e.currentTarget.name);
isClicked = true;
trace(left);
}
function matchingRight(e:MouseEvent):void{
var right:String = String(e.currentTarget.name);
trace(right);
if(isClicked == true && left.substring(3,3) == right.substring(3,3)){
trace("matched");
}
}
According to your code variable "left" is null at matchingRight method, because matchingLeft uses its local variable with name "left", and top-level "left" still has its default value.
also String.substring method is used incorrectly:
var name:String="p3.a1";
trace(name.substring(3, 3)); // this will always output empty string ""
trace(name.substring(4, 5)); // this will output "1" string
in conclusion I'd advise to use array indices (integers) instead of strings when calculating "matched" condition, substring operation and string comparison are CPU intensive.

in the dark about ajax instructions on arrays inside Autocomplete widget

I have an Autocomplete working with geonames.org cities in the source: option and want to manipulate some of the arrays in the results. I have a "hard coded" test version running, but am having trouble manipulating the array variables to turn it into something useful.
A short statement of the problem is I can't get the alert statements to output readable strings. I get [object, Object] types of output. I need readable strings in the arrays for other code (not shown) to work. But other problems are: the Firebug Console output does not occur, and the Console gives me the following error statement - Error: Permission denied to access property 'item.autocomplete' - from line 2 of jQuery. This does not happen with the hard coded test. This is my first time using .grep and I'm not comfortable with .map, so I'm pretty sure the problems are array manipulations in those 3 sections.
Here's some relevant code. All the variables are declared, but I don't show all the declarations below.
citiesWithBoroughs = //a global array variable, populated in a prior select: option
source: function (request, response){
$.ajax({
success: function ( data ){
var geonamesResponse=$.map(data.geonames, function (item){
return {
label: item.name //and others
}
}
alert(citiesWithBoroughs + "," + citiesWithBoroughs.length + "|cWB2" ); //displays correct info
var noBoroughs=$.grep( geonamesResponse, function ( item, i ) {
for (var i=0; i < citiesWithBoroughs.length; i++ )
if( item.label === citiesWithBoroughs[i] ){ //compare geonamesResponse to each citiesWithBoroughs
console.log(citiesWithBoroughs[i]); //nothing in Console
return false; //drop any matches out of the geonamesResponse array
}
noBoroughs = $.map( data.geonames, function (item){ return item.label; });
console.log(noBoroughs); //nothing appears in Console
return true;
});
alert(noBoroughs.length + "," + citiesWithBoroughs.length + "," + geonamesResponse.length + "|3lengths" ); //correct info
alert(noBoroughs + "|nB" ); //in test, shows correct number of [object,Object] but no data
if( noBoroughs.length != geonamesResponse.length ){
var dropdownsCityWithBoroughs = $.grep( geonamesResponse, function ( item, i ) {
for (var i=0; i<citiesWithBoroughs.length; i++ )
if(item.label === citiesWithBoroughs[i]){return false;}
return true;
}, true )//true inverts grep to return the has-Boroughs city in the dropdown
alert(dropdownsCityWithBoroughs + "|dCWB"); //contains object, Object, but shows no data
}
}
}
}
I'm a novice so please give specific comments and code. I don't follow general instructions well.
The short statement of my problem was I could not read the output of my alerts, which contain arrays. Turns out JSON.stringify() fixes that. Other problems, like the Console.log statements not showing continue, but I can deal with that mysterious problem when the alerts work.

JSON: How do I select an array inside another array?

I have the current JSON file:
[{"id":"1","images":[{"img_id":"1"},{"img_id":"2"},{"img_id":"3"}]},
[{"id":"2","images":[{"img_id":"1"},{"img_id":"2"},{"img_id":"3"}]}
How do I select the array with ID 1 and list every 'img_id' inside it, without repeating it for the other array?
edit 1:
I am trying to parse it like this but this code is erroneous:
$("#button").click(function() {
$.getJSON("../path/to/json", function(data) {
$.each(data[0].images.img_id, function(i,data){
var new_data ="<p src='path/to/folder/"+images.img_id+"'></p>";
$(new_data).appendTo("#htmlTag");
});
}); return false;
});
Much appreciated.
You have an array of objects, where each object contains another array of objects. I'm assuming the JSON structure you are using is:
var a = [{"id":"1","images":[{"img_id":"1"},{"img_id":"2"},{"img_id":"3"}]},
{"id":"2","images":[{"img_id":"1"},{"img_id":"2"},{"img_id":"3"}]}];
I'm also assuming you are using JavaScript.
PostEdit:
Your code is fairly close, I believe what I have below should work:
$("#button").click(function() {
$.getJSON("../path/to/json", function(data) {
$.each(data[0].images, function(i,data){
var new_data ="<p src='path/to/folder/" + data.img_id + "'></p>";
$(new_data).appendTo("#htmlTag");
});
});
return false;
});
All I did was change the first parameter to your each call from: data[0].images.img_id to: data[0].images. Also, I changed the declaration of new_data from:
var new_data ="<p src='path/to/folder/"+images.img_id+"'></p>";
to:
var new_data ="<p src='path/to/folder/"+data.img_id+"'></p>";
Note that the parameter "data" in the each callback function is simply the element in the array, while "i" is the index of that element in the array. Therefore, data is an object which looks like this:
{"img_id":1}
So, you can get the ID via data.img_id. Hope this helps.
I think you're talking about references. I don't think they are possible in JSON. In case you strictly need them and still want the readable serialization of your objects - I'd suggest you to look into YAML
I think there is a typo in your JSON...it seems like a bracket is missing at the end, and one has been added at the start of line 2. But, assuming you meant this (and are using Javascript):
var myJson = [{"id":"1","images":[{"img_id":"1"},{"img_id":"2"},{"img_id":"3"}]},
{"id":"2","images":[{"img_id":"1"},{"img_id":"2"},{"img_id":"3"}]}];
then you can access whatever you need just like a nested Javascript object. If you wanted to only access the object with ID equal to 1, and order is not guaranteed, you would have to iterate:
for(var i = 0; i < myJson.length; i++){
if(myJson[i].id === "1"){
var imgs = myJson[i].images;
for(var j = 0; j < imgs.length; j++){
//do what you want with imgs[j].img_id
}
}
}

Resources