I have a problem on parsing of my JSON data. On my object 2, I would have the "t_quartier" while the value is just a reference that points to the object 1.
How can I get this value if I'm on my item 2?
thank you a lot
You could use this:
angular.module('app').service('commonService', commonService);
function commonService() {
//DFS for fixing JSON references
var elements = {}
this.fixReferences = function (json) {
var tree = json;
for (var x in tree) {
if ((typeof (tree[x]) === 'object') && (tree[x] !== null)) {
var result = dfsVisit(tree[x]);
tree[x] = result;
}
}
return tree;
}
function dfsVisit(tree) {
for (var x in tree) {
if ((typeof (tree[x]) === 'object') && (tree[x] !== null)) {
var result = dfsVisit(tree[x]);
tree[x] = result;
}
}
if (tree["$ref"] !== undefined) {
var ref = tree.$ref;
if (elements[ref] !== undefined) {
tree = elements[ref];
}
} else if (tree["$id"] !== undefined) {
var element = tree;
elements[element.$id] = element;
}
return tree;
}
}
You could define that function wherever you want but a service would be a clean way.
For using it:
angular.module('app').factory('yourService', yourService);
/*#ngInject*/
function yourService($http, commonService) {
var service = {
get: get
};
return service;
function get() {
return $http.get('Your url').then(function (response) {
var fixedData = commonService.fixReferences(response.data);
return fixedData;
});
}
}
Related
I am building a Nodejs Note app and I am very new at this, so here the delete function doesn't work it, deletes everything from the array and I want to delete only title
There are two file app.js and note.js.
Here's the content of app.js file
if (command === "add") {
var note = notes.addNote(argv.title, argv.body);
if (note) {
console.log("Note created");
console.log("__");
console.log(`Title: ${note.title}`);
console.log(`Body: ${note.body}`);
} else {
console.log("The title has already exist")
}
} else if (command === "delete") {
var noteRemoved = notes.delNote(argv.title)
var message = noteRemoved ? "Note has been removed" : "Note not found";
console.log(message)
}
Here's the note.js content
var fetchNotes = function () {
try {
var noteString = fs.readFileSync("notes-data.json")
return JSON.parse(noteString);
} catch (e) {
return [];
}
};
var saveNotes = function (notes) {
fs.writeFileSync("notes-data.json", JSON.stringify(notes));
};
var addNote = function (title, body) {
var notes = fetchNotes();
var note = {
title,
body
};
var duplicateNotes = notes.filter(function (note) {
return note.title === title;
});
if (duplicateNotes.length === 0) {
notes.push(note);
saveNotes(notes);
return note;
};
}
var delNote = function (title) {
var notes = fetchNotes();
var filteredNotes = notes.filter(function (note) {
note.title !== title;
});
saveNotes(filteredNotes);
return notes.length !== filteredNotes.length
}
You miss return statement in delNote filter function
var filteredNotes = notes.filter(function (note) {
return note.title !== title;
});
or we can use es6 syntax:
const filteredNotes = notes.filter(note => note.title !== title);
You need to add return note.title !== title; in delNote function.
My filterProducts function makes a call to findIntersection which is present but I get an error findIntersection is undefined.
angular.module('BrandService', [])
.service('BrandService', function ($filter, DataService) {
var productDb;
var products;
return {
filterProducts(brands, priceRange) {
var filteredProducts = [];
var brandProducts = [];
var priceProducts = [];
var productsArray = [];
var brandChecked = false;
var priceChecked = false;
angular.forEach(brands, function (brand) {
if (brand.checked) {
brandChecked = true;
angular.extend(brandProducts,
$filter('filter')(productDb, { 'brand': brand.name }));
}
if (brandChecked) {
productsArray.push(brandProducts);
console.log('brandProducts = ', brandProducts)
}
});
angular.forEach(priceRange, function (price) {
if (price.checked) {
priceChecked = true;
let filteredProductDb = productDb.filter((prod) => {
return (prod.price >= price.low && prod.price <= price.high);
});
angular.extend(priceProducts, filteredProductDb);
}
});
if (priceChecked) {
productsArray.push(priceProducts);
// console.log('priceProducts = ', priceProducts)
}
if (!brandChecked && !priceChecked) {
filteredProducts = products;
} else {
if (productsArray.length > 1) {
filteredProducts = findIntersection(productsArray);
} else {
filteredProducts = productsArray[0];
}
}
return filteredProducts;
},
findIntersection(productsArray) {
console.log('findIntersection called')
var filteredProducts = [];
var filteredSet = new Set();
for(var i=0; i < productsArray.length - 1; i++) {
var products1 = productsArray[i];
var products2 = productsArray[i+1];
angular.forEach(products1, function(product1) {
angular.forEach(products2, function(product2) {
if(product1._id == product2._id) {
filteredSet.add(product1);
}
});
});
}
filteredProducts = Array.from(filteredSet);
return filteredProducts;
}
}
})
My filterProducts function makes a call to findIntersection which is present but I get an error findIntersection is undefined.
My filterProducts function makes a call to findIntersection which is present but I get an error findIntersection is undefined.
You are returning a javascript object with properties. You are not defining global functions.
You need to store the service returned before :
var service = { findProducts: ... , findIntersection: ... };
return service;
And instead of calling findIntersection, call service.findIntersection.
You have to make a reference to local object.
Simply change this: filteredProducts = findIntersection(productsArray);
to this: filteredProducts = this.findIntersection(productsArray);
I need to push a JSON object to AngularJS and need to check before if the value for one of the objects exist. I need to overwrite the data.
$scope.setData = function(survey, choice) {
keepAllData.push({
'surveyId': survey.id,
'choiceId': choice.id
});
console.log(keepAllData);
toArray(keepAllData);
alert(JSON.stringify(toArray(keepAllData)));
$scope.keepAllDatas.push({
'surveyId': survey.id,
'choiceId': choice.id
});
var items = ($filter('filter')(keepAllDatas, {
surveyId: survey.id
}));
}
function toArray(obj) {
var result = [];
for (var prop in obj) {
var value = obj[prop];
console.log(prop);
if (typeof value === 'object') {
result.push(toArray(value));
console.log(result);
} else {
result.push(value);
console.log(result);
}
}
return result;
}
If the survey id exists in keepalldata, I need to change the recent value with choiceid. Is it possible to do with AngularJS?
Try with this: Before pushing data you have to check if the survey id exists or not. If it exists you have to update choice with the corresponding survey id, otherwise you can push directly.
$scope.setData = function(survey, choice) {
var item = $filter('filter')(keepAllData, {
surveyId: survey.id
});
if (!item.length) {
keepAllData.push({
'surveyId': survey.id,
'choiceId': choice.id
});
} else {
item[0].choiceId = choice.id;
}
console.log(keepAllData);
}
Demo
$scope.keepAllDatas = [];
$scope.setData = function(survey, choice) {
if($scope.keepAllDatas.length == 0) {
$scope.keepAllDatas.push({'surveyId':survey.id,'choiceId':choice.id});
}
else {
var items = ($filter('filter')( $scope.keepAllDatas, {surveyId: survey.id }));
for (var i = items.length - 1; i >= 0; i--) {
// alert(items[i].surveyId);
if(items[i].surveyId == survey.id) {
console.log($scope.keepAllDatas.indexOf(survey.id));
$scope.keepAllDatas.splice($scope.keepAllDatas.indexOf(survey.id),1);
console.log("Removed data")
}
}
$scope.keepAllDatas.push({'surveyId':survey.id, 'choiceId':choice.id});
console.log( $scope.keepAllDatas)
// alert(items[0].surveyId);
}
}
I'm trying to call my mapper function recursively but getting the error not defined: 'ReferenceError: mapper is not defined at Object.mapper'
Could use some guidance on how to call the function recursively in this particular situation.
angular.module('dvb.transferObjects').value('MappedTransferObject', function(obj1) {
'use strict';
return {
mapper: function(obj2) {
for (var p in obj1) {
if (typeof obj1[p] === 'object') {
mapper(obj1[p], obj2[p]);
} else {
if(obj2.hasOwnProperty(p)) {
obj1[p] = obj2[p];
}
}
}
return obj1;
}
};
});
I'm injecting this value in my controller as MTO and using it as follows:
var mto = new MTO(appState.getTemplateObject());
var mappedObject = mto.mapper($scope.dvModel);
If you add a name to your anonymous function you can call it inside itself like so:
angular.module('dvb.transferObjects').value('MappedTransferObject', function (obj1) {
'use strict';
return {
mapper: function mapper(obj2) {
for (var p in obj1) {
if (typeof obj1[p] === 'object') {
mapper(obj1[p], obj2[p]);
} else {
if (obj2.hasOwnProperty(p)) {
obj1[p] = obj2[p];
}
}
}
return obj1;
}
};
});
The reason you can not use mapper in your example is due to the mapper being scoped to the object itself. This means the only way to access the function would be to call it through the object, which you can't do without saving off a reference to the object before returning it:
angular.module('dvb.transferObjects').value('MappedTransferObject', function (obj1) {
'use strict';
var mapper = {
mapper: function (obj2) {
for (var p in obj1) {
if (typeof obj1[p] === 'object') {
mapper.mapper(obj1[p], obj2[p]);
} else {
if (obj2.hasOwnProperty(p)) {
obj1[p] = obj2[p];
}
}
}
return obj1;
}
};
return mapper;
});
Let's say I have a following template:
"foo['x'] = '{{ myVar }}';"
Is there an angular way of checking if evaluating this against my current scope will give myVar some value ? I've got an array of such small templates and I only want to include them in the document when values are truthy. I was hoping either $interpolate, $parse or $eval might come in handy here. I know for sure that $interpolate is useless. What about the other two ? Maybe it's at least possible to get the name of the assigned value/expression ?
EDIT
I wasn't specific enough. What I was trying to achieve, was checking in advance if for example template '{{ myVar }}' evaluated against the current scope will return an empty string or value of the scope variable (if it exists). The case was really specific - when traversing an array of short templates I wanted to know if a template will return as an empty string or not, and only include it in my final html if it doesn't.
I'm not sure what are you trying to achieve, but to if you want to check if myVar is truthy in current scope, you can:
{{myVar ? "aw yiss" : "nope"}}
Evaluates to "aw yiss" if myVar is truthy and "nope" otherwise.
I ended up with a modified $interpolate provider but maybe someone knows a shorter solution :
app.provider('customInterpolateProvider', [
function $InterpolateProvider() {
var startSymbol = '{{';
var endSymbol = '}}';
this.startSymbol = function(value){
if (value) {
startSymbol = value;
return this;
} else {
return startSymbol;
}
};
this.endSymbol = function(value){
if (value) {
endSymbol = value;
return this;
} else {
return endSymbol;
}
};
this.$get = ['$parse', '$sce', function($parse, $sce) {
var startSymbolLength = startSymbol.length,
endSymbolLength = endSymbol.length;
function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {
allOrNothing = !!allOrNothing;
var startIndex,
endIndex,
index = 0,
expressions = [],
parseFns = [],
textLength = text.length,
exp;
var getValue = function (value) {
return trustedContext ?
$sce.getTrusted(trustedContext, value) :
$sce.valueOf(value);
};
var stringify = function (value) {
if (value == null) {
return '';
}
switch (typeof value) {
case 'string':
break;
case 'number':
value = '' + value;
break;
default:
value = angular.toJson(value);
}
return value;
};
var parseStringifyInterceptor = function(value) {
try {
return stringify(getValue(value));
} catch(err) {
console.err(err.toString());
}
};
while(index < textLength) {
if ( ((startIndex = text.indexOf(startSymbol, index)) !== -1) &&
((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) !== -1) ) {
exp = text.substring(startIndex + startSymbolLength, endIndex);
expressions.push(exp);
parseFns.push($parse(exp, parseStringifyInterceptor));
index = endIndex + endSymbolLength;
} else {
break;
}
}
if (!expressions.length && !text.contains(startSymbol) && !text.contains(endSymbol)) {
expressions.push(text);
}
if (!mustHaveExpression) {
var compute = function(values) {
for(var i = 0, ii = expressions.length; i < ii; i++) {
if (allOrNothing && angular.isUndefined(values[i])) {
return;
}
expressions[i] = values[i];
}
return expressions.join('');
};
return angular.extend(function interpolationFn(context) {
var i = 0;
var ii = expressions.length;
var values = new Array(ii);
try {
if (ii && !parseFns.length) {
return expressions[0];
} else {
for (; i < ii; i++) {
values[i] = parseFns[i](context);
}
return compute(values);
}
} catch(err) {
console.err(err.toString());
}
}, {
exp: text,
expressions: expressions,
$$watchDelegate: function (scope, listener, objectEquality) {
var lastValue;
return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {
var currValue = compute(values);
if (angular.isFunction(listener)) {
listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);
}
lastValue = currValue;
}, objectEquality);
}
});
}
}
return $interpolate;
}];
}
]);
Lines below were added because in some cases I have a predefined text in my short template and I always want to render it :
if (!expressions.length && !text.contains(startSymbol) && !text.contains(endSymbol)) {
expressions.push(text);
}
if (ii && !parseFns.length) {
return expressions[0];
} else {