Provide different bindings of same data - javascript

Using AngularJS, say an array $scope.data.children has item with the following structure:
{
"sku" : "<sku>",
"selected" : "<boolean>"
}
Would there be a simple way referencing all selected = true children, ideally represented in $scope.data.components?
So, for example, if
$scope.data.children = [
{"sku" : "A","selected" : "true"},
{"sku" : "B","selected" : "false"},
{"sku" : "C","selected" : "true"},
{"sku" : "D","selected" : "false"}
]
then
$scope.data.components = [
{"sku" : "A","selected" : "true"},
{"sku" : "C","selected" : "true"},
]
and if $scope.data.children is updated to [{"sku" : "D","selected" : "true"}]
then $scope.data.components =,
[
{"sku" : "A","selected" : "true"},
{"sku" : "C","selected" : "true"},
{"sku" : "D","selected" : "true"}
]

$scope.$watch("data.children", setSelected);
var setSelected = function () {
var selected = []
for (var i = 0; i < $scope.data.children; i++) {
if ($scope.data.children[i].selected == "true") {
selected.push($scope.data.children[i];
}
}
$scope.data.components = selected;
}

try to use underscore.js in your project.
it makes your life 500% easier!
and your item.selected value is stored as string, not as boolean.
$scope.data.children = _.filter($scope.data.components, function (item) {
return item.selected == "true";
});
http://underscorejs.org/#filter

Related

How can I access(and convert) 'date' to Javascript?

Here is MongoDB scheme.
{
"_id" : ObjectId("222222"),
"active" : false,
"amount" : "15%",
"description" : "15% discount",
"name" : "20200628-test",
"policies" : {
"apply" : [
{
"name" : "expiryDate",
"params" : {
"date" : ISODate("2020-07-06T14:59:59.999Z")
}
},
{
"name" : "isApplyCategoryExist"
}
],
"discount" : [],
"conflict" : [
{
"name" : "exclusive"
}
],
"grant" : []
},
"target" : {
"sku" : "",
"products_ids" : [],
"category_ids" : [
ObjectId("11111111")
]
},
"title" : "15% coupon"
}
I want to access date.
For example, "policies.apply.params.date"...
I don't know how to access 'date' to Javascript.
Please let me know...
apply is an array, so you have to give it index which you want to get.
var num = 0; // pick up an array number you want
var date = policies.apply[num].params.date;
Your policies.apply is an array so if you want to access "2020-07-06T14:59:59.999Z", you should do this:
policies.apply[0].params.date
But the "policies.apply[1]" doesn't have params (params.date also) so you can write a function to get date like this:
function get_apply_date(index) {
if(policies.apply[index].params && policies.apply[index].params.date)
return policies.apply[index].params.date;
return undefined; // or null
}

object.push(array) is not working

I am using for loop to get the units onebyone and inside loop I am getting the array of volumes like below. now I want to push that array to respective unit so I used push but here I am getting error.
My code is below
$scope.UnitDetails = [{
UnitId : "001"
Unit1 : "A"
Fields: [{"one" : "true","Isactive" : true },
{"two" : "false","Isactive" : true }
]
},
{
UnitId : "002"
Unit1 : "B"
Fields: [{"one" : "true","Isactive" : true },
{"two" : "false","Isactive" : true }
]
}]
for(i= 0; i < $scope.UnitDetails.length ; i++){
var volume = [];
volume.Volume_AL = eval($scope.VolumeFormula.AL);
volume.Volume_BL = eval($scope.VolumeFormula.BL);
volume.Volume_CL = eval($scope.VolumeFormula.CL);
volume.Volume_DL = eval($scope.VolumeFormula.DL);
$scope.UnitDetails[i].push(volume);
}
Can anyone find where i am doing mistake
EDIT
When I try as below then it is creating another array in object as below
for(i= 0; i < $scope.UnitDetails.length ; i++){
var volume = {};
volume.Volume_AL = eval($scope.VolumeFormula.AL);
volume.Volume_BL = eval($scope.VolumeFormula.BL);
volume.Volume_CL = eval($scope.VolumeFormula.CL);
volume.Volume_DL = eval($scope.VolumeFormula.DL);
$scope.UnitDetails.push(volume);
}
What I got
$scope.UnitDetails = [{
UnitId : "001"
Unit1 : "A"
Fields: [{"one" : "true","Isactive" : true },
{"two" : "false","Isactive" : true }
]
},
{
UnitId : "002"
Unit1 : "B"
Fields: [{"one" : "true","Isactive" : true },
{"two" : "false","Isactive" : true }
]
},
{
Volume_CL:0,
Volume_EQ:12,
Volume_PH:54,
Volume_RW: 24
}]
My Expected :
$scope.UnitDetails = [{
UnitId : "001"
Unit1 : "A"
Fields: [{"one" : "true","Isactive" : true },
{"two" : "false","Isactive" : true }
]
volume : [ {
Volume_CL:0,
Volume_EQ:12,
Volume_PH:54,
Volume_RW: 24
}]
},
{
UnitId : "002"
Unit1 : "B"
Fields: [{"one" : "true","Isactive" : true },
{"two" : "false","Isactive" : true }
]
volume : [ {
Volume_CL:0,
Volume_EQ:12,
Volume_PH:54,
Volume_RW: 24
}]
},
]
To achieve the desired result you could append the volume array dynamically to each element of $scope.UnitDetails:
for (var i = 0; i < $scope.UnitDetails.length; i++) {
$scope.UnitDetails[i].volume = [{
Volume_AL: eval($scope.VolumeFormula.AL),
Volume_BL: eval($scope.VolumeFormula.BL),
Volume_CL: eval($scope.VolumeFormula.CL),
Volume_DL: eval($scope.VolumeFormula.DL)
}];
}
Remark: The eval statement allows for execution of arbitrary javascript code and if the input is coming from your users you might want to ensure that it doesn't contain any malicious code before passing it to this function. Or even better do not use eval at all. Depending on your requirements you might find a more appropriate and restrictive function to achieve your goal. For example if you are expecting to evaluate only mathematical expressions written from your clients you might find a library designed exactly for this purpose rather than using the general purpose eval statement.

Compare,add,update,delete elements on array of mongodb

Need help on operation like update,delete,add,upsert,delete on below document of MongoDB.
Below is MongoDB document that exists in temp collection.
{
"local_id" : "1841",
"name_first" : "tiger",
"name_last" : "lion",
"address" : [
{
"id" : 1,
"address_type" : "Home",
"city" : "Delhi",
"country" : "",
"po_box" : ""
},
{
"id" : 2,
"address_type" : "Work",
"city" : "",
"country" : "",
"po_box" : ""
}
],
"email" : [
{
"email_id" : "blah#gmail.com",
"id" : 1,
"type" : "Home"
},
{
"email_id" : "Pearl1#gmail.com",
"id" : 2,
"type" : "Work"
}
],
"phone_number" : [
{
"id" : 1,
"no" : "+911234567890",
"type" : "Mobile"
},
{
"id" : 2,
"no" : "+917894561230",
"type" : "work"
}
]
}`
Now I have some document like below, i want query that will compare,add,update,delete on my above document.
`
{
"local_id" : "1730",
"name_first" : "lion",
"name_last" : "king",
"address" : [
{
"id" : 1,
"address_type" : "Home",
"city" : "Delhi",
"country" : "India",
"po_box" : "110041"
},
{
"id" : 2,
"address_type" : "Work",
"city" : "Delhi-NCR",
"country" : "India",
"po_box" : "110048"
},
{
"id" : 3,
"address_type" : "Work",
"city" : "Delhi-NCR",
"country" : "Indai",
"po_box" : "110048"
}
],
"email" : [
{
"email_id" : "updatethis#gmail.com",
"id" : 1,
"type" : "Home"
},
{
"email_id" : "Pearl1#gmail.com",
"id" : 2,
"type" : "Work"
},
{
"email_id" : "addthisarray#gmail.com",
"id" : 3,
"type" : "personal"
}
],
"phone_number" : [
{
"id" : 1,
"no" : "+911234567890",
"type" : "Mobile"
}
/*second array not here so remove that array from that document*/
]
}`
You can save function on server as you can call that function to get the differences, as below.
db.system.js.save({
_id: "getupdatedArray",
value: function(obj1, obj2) {
var VALUE_CREATED = 'created';
var VALUE_UPDATED = 'updated';
var VALUE_DELETED = 'deleted';
var VALUE_UNCHANGED = 'unchanged';
function map(obj1, obj2) {
if (isValue(obj1) || isValue(obj2)) {
return {
type: compareValues(obj1, obj2),
old: obj1,
new: obj2
};
}
var diff = {};
for (var key in obj1) {
if (isFunction(obj1[key])) {
continue;
}
var value2 = undefined;
if ('undefined' != typeof(obj2[key])) {
value2 = obj2[key];
}
diff[key] = map(obj1[key], value2);
}
for (var key in obj2) {
if (isFunction(obj2[key]) || ('undefined' != typeof(diff[key]))) {
continue;
}
diff[key] = map(undefined, obj2[key]);
}
return diff;
}
function compareValues(value1, value2) {
if (value1 === value2) {
return VALUE_UNCHANGED;
}
if ('undefined' == typeof(value1)) {
return VALUE_CREATED;
}
if ('undefined' == typeof(value2)) {
return VALUE_DELETED;
}
return VALUE_UPDATED;
}
function isFunction(obj) {
return {}.toString.apply(obj) === '[object Function]';
}
function isArray(obj) {
return {}.toString.apply(obj) === '[object Array]';
}
function isObject(obj) {
return {}.toString.apply(obj) === '[object Object]';
}
function isValue(obj) {
return !isObject(obj) && !isArray(obj);
}
return map(obj1, obj2);
}
})
Then you can call function as below..
db.loadServerScripts();
getupdatedArray({"a": "abc"}, {"a": "a111", "b": "bbb"});
This will give you result as below:
{
"a" : {
"type" : "updated",
"old" : "abc",
"new" : "a111"
},
"b" : {
"type" : "created",
"old" : undefined,
"new" : "bbb"
}
}
Thanks
Satish Lakhani

Changing node text in jsTree

I'm a longtime JavaScript coder but new to jQuery. I'm using jsTree and need to change a node name. I've searched for and tried many examples from this site and others, but can't find a solution that works. Basically, I'm trying to change a tree node name but it always renames to 'undefined'. In the following example, whenever a node is selected the text should change.
The block of code that is supposed to make the change is:
$('#catTree')
// listen for event
.on('changed.jstree', function (e, data) {
var node = data.instance.get_node(data.selected[0])
var newText = "Some new text";
$('#catTree').jstree('rename_node', [node , newText] );
})
In case is it something obvious that I'm just missing, here the whole example:
<div id="catTree" class="demo"></div>
<script>
var catData = [
{ "id" : "allCategories", "parent" : "#", "type" : "catRoot", "text" : "All categories" },
{ "id" : "category1", "parent" : "allCategories", "type" : "category", "text" : "Category 1" },
{ "id" : "category2", "parent" : "allCategories", "type" : "category", "text" : "Category 2" },
{ "id" : "category3", "parent" : "allCategories", "type" : "category", "text" : "Category 3" },
]
$.jstree.defaults.core = {
strings : false,
check_callback : true,
animation : 100,
aria_roles : true,
multiple : false,
themes : {
name : false,
url : true,
dots : true,
icons : true,
dir : false
},
base_height : false
};
$('#catTree')
// listen for event
.on('changed.jstree', function (e, data) {
var node = data.instance.get_node(data.selected[0])
var newText = "Some new text";
$('#catTree').jstree('rename_node', [node , newText] );
})
$(function () {
$("#catTree").jstree({
'core' : {
'data' : catData
},
"types" : {
"category" : { "icon" : "none", "max_children" : 1, "valid_children" : ["pasteText"] },
},
"crrm" : {
"move" : {
"check_move" : function (m) {
var p = this._get_parent(m.o);
if(!p) return false;
p = p == -1 ? this.get_container() : p;
if(p === m.np) return true;
if(p[0] && m.np[0] && p[0] === m.np[0]) return true;
return false;
}
}
},
"dnd" : {
"drop_target" : false,
"drag_target" : false
},
"plugins" : [ "themes", "html_data", "crrm", "dnd", "types" ]
});
});
</script>
I'm using jsTree v3.2.1 and jQuery v2.1.4
you don't have to get node because you can access it from data variable.
call rename_node as $('#catTree').jstree('rename_node', data.node, newText) instead of $('#catTree').jstree('rename_node', [node , newText] )
also move your .on code to the main jstree init function
So the code will look like below. See example JS Fiddle.
$(function () {
$("#catTree").on('changed.jstree', function (e, data) {
var newText = "Some new text";
$('#catTree').jstree('rename_node', data.node, newText);
})
.jstree({
'core' : {
'data' : catData
},
"types" : {
"category" : { "icon" : "none", "max_children" : 1, "valid_children" : ["pasteText"] },
},
"crrm" : {
"move" : {
"check_move" : function (m) {
var p = this._get_parent(m.o);
if(!p) return false;
p = p == -1 ? this.get_container() : p;
if(p === m.np) return true;
if(p[0] && m.np[0] && p[0] === m.np[0]) return true;
return false;
}
}
},
"dnd" : {
"drop_target" : false,
"drag_target" : false
},
"plugins" : [ "themes", "html_data", "crrm", "dnd", "types" ]
});
});

merging two data structures of different shapes

I have two data structures with different shapes that come from two different API's. The data is in JSON format, language is JavaScript.
Array 1:
[ { "document" : { "html" : "some_html", "name" : "DOCUMENT_NAME_1" },
"tooltips" : [ { "html" : "some_html", "name" : "TASK_NAME_1" },
{ "html" : "some_html", "name" : "TASK_NAME_2" } ] },
{ "document" : { "html" : "some_html", "name" : "DOCUMENT_NAME_2" },
"tooltips" : [ { "html" : "some_html", "name" : "TASK_NAME_3" },
{ "html" : "some_html", "name" : "TASK_NAME_4" } ] }]
Array 2:
[ [ { "name" : "TASK_NAME_1", "status" : "FINISHED" },
{ "name" : "TASK_NAME_2", "status" : "OPEN" } ],
[ { "name" : "TASK_NAME_3", "status" : "OPEN" },
{ "name" : "TASK_NAME_4", "status" : "FUTURE" } ] ]
The elements of the tooltips field from the array 1 contain the same "name"s as elements of array 2. How can I elegantly merge "status" from the array 2 into tooltips within array 1?
I thought that lenses could be the right answer, but I'm unsure as I've never used them.
I am aware of some ways I could solve it using nested iteration and updating array 1. I am ideally looking for an approach that doesn't modify existing data structures.
This is little complex but it should work for you
array2.forEach(function(tooltips){
tooltips.forEach(function(tooltip){
for (var i = 0; i < array1.length; i++) {
for (var j = 0; j < array1[i].tooltips.length; j++) {
var arr1Tooltip = array1[i].tooltips[j];
if(arr1Tooltip.name == tooltip.name)
arr1Tooltip.status = tooltip.status;
};
};
});
});
console.log(JSON.stringify(array1));
This is probably way over engineered and not very efficient, but you can do it as with this JSFiddle using recursive functions. I'm too tired to do it in a clever way.
var arr1 = [ { "document" : { "html" : "some_html", "name" : "DOCUMENT_NAME_1" },
"tooltips" : [ { "html" : "some_html", "name" : "TASK_NAME_1" },
{ "html" : "some_html", "name" : "TASK_NAME_2" } ] },
{ "document" : { "html" : "some_html", "name" : "DOCUMENT_NAME_2" },
"tooltips" : [ { "html" : "some_html", "name" : "TASK_NAME_3" },
{ "html" : "some_html", "name" : "TASK_NAME_4" } ] }];
var arr2 = [ [ { "name" : "TASK_NAME_1", "status" : "FINISHED" },
{ "name" : "TASK_NAME_2", "status" : "OPEN" } ],
[ { "name" : "TASK_NAME_3", "status" : "OPEN" },
{ "name" : "TASK_NAME_4", "status" : "FUTURE" } ] ];
var findStatus = function(name, searchArray) {
var r = '';
if (typeof searchArray === 'object') {
if ("name" in searchArray && "status" in searchArray) {
if (searchArray.name == name) {
return searchArray.status;
} else {
return '';
}
} else {
for (var i in searchArray) {
r = findStatus(name, searchArray[i]);
if (r != '') {
return r;
}
}
}
}
return '';
};
var updateStatus = function(arrToUpdate, arrWithStatus) {
var copy = $.extend(true, {}, arrToUpdate);
var r = '';
if (typeof copy === 'object') {
if ("name" in copy) {
r = findStatus(copy.name, arrWithStatus);
if (r != '') {
copy.status = r;
}
} else {
for (var i in copy) {
copy[i] = updateStatus(copy[i], arrWithStatus);
}
}
}
return copy;
};
var arr3 = updateStatus(arr1, arr2); // Final combined array
I added the var copy = $.extend(true, {}, arrToUpdate); line so that it will do a deep copy and not modify the original array, as a result, it requires jQuery.
Since your data structure is nested, you will need two zip.map/zipWiths:
zip(array1, array2).map(function([obj, tooltips]) { // ES6 destructuring syntax
return {
document: obj.document,
tooltips: zip(obj.tooltips, tooltips).map(function([tooltip, extender]) {
return {
html: tooltip.html,
name: tooltip.name,
status: extender.status
};
})
};
})
If you don't like to repeat those object literal structures, you might be able to use some copying function; for example
extend({}, document, {tooltips:…})
extend({}, tooltip, extender);
You also might use a lenses library like https://github.com/DrBoolean/lenses or https://github.com/fantasyland/fantasy-lenses for that, but I'm not sure whether that's worth the effort - the above code only needs underscore/lodash.
To get around the inner zipWith, you would need a Traversal lens (I assume you're familiar with this article), but I haven't yet seen a JavaScript library that offers such.

Categories

Resources