I've tried for some time now to figure out how to data-bind a child in an object in Knockout js. I hope someone can help me solve this :)
I want to display the obj.externalLinks.facebook. I can't figure out how to data-bind it. This is what I have:
Model:
var obj = ko.observable();
var data = { "id" : 1,
"itemName" : "item name",
"price": 250,
"ticketLink" : "http://google.com",
"externalLinks" : [
{ "homePage" : "http://google.com" },
{ "mySpace" : "http://myspace.com" },
{ "facebook" : "http://facebook.com" },
{ "wikipedia" : "http://en.wikipedia.org/" },
{ "facebookEventPage" : "http://facebook.com" }
]
}
obj(data);
ko.applyBindings(obj)
View:
<h1 data-bind="text: externalLinks[2]"></h1>
I know the data-bind part is wrong, but how do I do it? :(
Try this one
Html
<span data-bind="text: link('facebook')"></span>
JavaScript
var data = { "id" : 1,
"itemName" : "item name",
"price": 250,
"ticketLink" : "http://google.com",
"externalLinks" : [
{ "homePage" : "http://google.com" },
{ "mySpace" : "http://myspace.com" },
{ "facebook" : "http://facebook.com" },
{ "wikipedia" : "http://en.wikipedia.org/" },
{ "facebookEventPage" : "http://facebook.com" }]
};
var ViewModel = function(rawData){
var self = this;
var data = rawData;
self.link = function(linkKey){
for (var i=0; i<data.externalLinks.length; i++){
var item = data.externalLinks[i];
if(item[linkKey]){
return item[linkKey];
}
}
};
};
ko.applyBindings(new ViewModel(data));
So you can bind to the link by linkKey
jsfiddle sample
Related
I want to write a utility which connects to a REST api downloads data in JSON format and then paints the data as nested tables using Bootstrap.
JSON Data -
[
{
"id" : "Id1",
"name" : "Name1",
"orders" : [{"orderId" : "o1", "size" : 34}, {"orderId" : "o2", "size" : 3}]
},
{
"id" : "Id2",
"name" : "Name2",
"orders" : [
{"orderId" : "o3", "size" : 5, "addresses" : [{"addressId" : "a1", "phone" : "1235"}, {"addressId" : "a2", "phone" : 555}]},
{"orderId" : "o4", "size" : 5, "addresses" : [{"addressId" : "a3", "phone" : "1235"}]}
]
}
]
I looked at the sub-table feature of Bootstrap, however it seems that it would need lot of custom code to get this working. Is there a better way to bind the json to table in a generic way?
Edit
After spending some time I was able to achieve this -
As you can see, I could get one level of nesting, however i just need to go one level deep. Any suggestions?
<script>
var $table = $('#table')
function buildTable($el, jsonData) {
var i; var j; var row
var columns = []
var data = []
if(!Array.isArray(jsonData) && jsonData.length == 0) {
return;
}
Object.keys(jsonData[0]).forEach( (k) => {
columns.push({
field: k,
title: k,
sortable: true
})
})
for(var j = 0; j < jsonData.length; j++) {
row = {}
Object.keys(jsonData[j]).forEach( (k) => {
row[k] = jsonData[j][k]
})
data.push(row)
}
$el.bootstrapTable({
columns: columns,
data: data,
detailFilter: function (index, row) {
console.log("detail filter " + Object.values(row))
for(var k in row) {
if(Array.isArray(row[k])){
return true;
}
}
return false;
},
onExpandRow: function (index, row, $detail) {
console.log("expand row keys " + Object.keys(row))
console.log("expand row vals " + Object.values(row))
var newRow = {};
for(var k in row) {
if(Array.isArray(row[k])){
alert('found ' + row[k])
newRow = row[k]
break
}
}
buildTable($detail.html('<table></table>').find('table'), newRow)
}
})
};
var mydata =
[
{
"id": 0,
"name": "test0",
"price": "$0",
"orders" :
[
{
"name" : "ABC",
"size" : 25,
"someList": [{"a":1, "b":2}, {"a":3, "b":4}]
},
{
"name" : "XYZ",
"size" : 50
}
]
}
/* {
"id": 1,
"name": "test1",
"price": "$1"
},
{
"id": 2,
"name": "test2",
"price": "$2",
"orders" : [{"name" : "def", "size": 45}]
}*/
];
$(function() {
buildTable($table, mydata)
})
I am trying to sort a nested list of json objects on one of the properties of which is a "date" field. The date field is in MM/dd/yyyy format.
This is the HTML code:
<body ng-app="Test" ng-controller="TestController as testCtrl" ng-init="testCtrl.displayList()">
<ul ng-repeat="de in testCtrl.listToBeDisplayed">
<li >{{ de.empId }} {{ de.empName }} {{ de.joinDate }}</li>
</ul>
<button type="button" ng-click="testCtrl.sortList()">Test Button</button>
// This is the script:
<script>
angular.module("Test",[]);
angular.module("Test").controller("TestController",TestController);
TestController.$inject = ['orderByFilter','$filter'];
function TestController(orderBy,$filter){
vm = this;
vm.demoList = [
{
"Employees" :
[{
"id" : "1001",
"name": "Andre",
"date": "05/20/2016"
},
{
"id" : "1002",
"name": "Chris",
"date": "04/11/2016"
},
{
"id" : "1003",
"name": "Darren",
"date": "03/11/2016"
},
{
"id" : "1004",
"name": "Marlen",
"date": "08/11/2016"
}]
}
];
propertyName = 'date';
vm.displayList = function(){
console.log("in display List fn");
empList=[];
for(var i=0;i<vm.demoList[0].Employees.length;i++)
{
value = vm.demoList[0].Employees[i];
console.log("value="+value);
var employee = {
empId: '',
empName: '',
joinDate: ''
};
employee.empId = value.id;
employee.empName = value.name;
employee.joinDate = $filter('date')(new Date(value.date), "MM/dd/yyyy");
empList[i] = employee;
}
vm.listToBeDisplayed = empList;
}
</script>
</body>
When I click the button, the list is not getting sorted properly.
I have referred Angular documentation for orderBy filter: https://docs.angularjs.org/api/ng/filter/orderBy
This is the plunker I created for the above situation:
https://plnkr.co/edit/Q1m24arssRxC6B3NNO0n?p=preview
Any help on this ?
Call the correct function in your html:
<button type="button" ng-click="testCtrl.sortList()">Test Button</button>
And order on correct property name:
vm.sortList = function () {
vm.listToBeDisplayed = orderBy(empList, 'joinDate', true);
}
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" ]
});
});
I have been trying to figure this out, but I seem to be going nowhere. Basically I have a JSON that outputs.
[
{
"gosuResponse" : {
"tokenId" : "60e2d532-3d1c-4a95-adbd-aa352984c125",
"page" : 1,
"pageSize" : 1000,
"nbLinesTotal" : 15,
"serials" : {
"serial" : [ "272072207980" ]
},
"data" : {
"row" : [ {
"col" : [ "2015-02-10", "", "1"]
}, {
"col" : [ "2015-02-10", "BNP-Blogs", "1504"]
}, {
"col" : [ "2015-02-10", "BNP", "66"]
}, {
"col" : [ "2015-02-10", "GOOMPlayer-Site", "6"]
}, {
"col" : [ "2015-02-10", "podcast", "19"]
}, {
"col" : [ "2015-02-10", "stream", "10"]
}, {
"col" : [ "2015-02-09", "", "6"]
}, {
"col" : [ "2015-02-09", "BNP-Blogs", "1742"]
}, {
"col" : [ "2015-02-09", "BNP", "61"]
}, {
"col" : [ "2015-02-09", "GOOMPlayer-Site", "2"]
}, {
"col" : [ "2015-02-09", "podcast", "18"]
}, {
"col" : [ "2015-02-09", "stream", "8"]
}, {
"col" : [ "2015-02-08", "", "7"]
}, {
"col" : [ "2015-02-01", "stream", "8"]
} ]
}
}
}
]
Since there are similar names, I grouped them together using underscore.js
var items = result[0].gosuResponse.data.row;
var groups = _(items).groupBy(function(o) {
return o.col[1];
});
console.log(groups);
This outputs,
Object
- BNP : Array[4]
- 0 : Object
- col : Array[3]
0 : '2015-02-10"
1 : 'BNP'
2: '66'
- 1 : Object
- col : Array[3]
0 : '2015-02-10"
1 : 'BNP'
2: '66'
I am trying to add up the number value in position 2 for each Object.
I tested with one key in my Plunkr, but I was wondering if there is a way to do it for all objects?
My Plunkr http://plnkr.co/edit/nNwNoAiUz4PKV8ucaPc1?p=preview
I think there is no reasons to group items:
var sum = {};
_.each(items, function(row) {
var col = row.col;
if (sum.hasOwnProperty(col[1])) {
sum[col[1]] += parseInt(col[2]) || 0;
} else {
sum[col[1]] = parseInt(col[2]) || 0;
}
});
But note I'm relatively new to underscore.js and did not know much about its specific tricks.
Update:
I've found a native underscore.js solution with using groups also:
var groups = _(items).groupBy(function(o) {
return o.col[1];
});
var sum2 = {};
_.each(groups, function(group, key) {
sum2[key] = _.reduce(group, function(memo, item) {
return memo + (parseInt(item.col[2]) || 0);
}, 0);
});
I have a series of ajax json responses that I need to convert to a common type of array. The issue is that each json response is slightly different.
Here are two examples of responses I might receive:
var contacts = [{ "ContactId" : "1", "ContactName" : "Bob" },{ "ContactId" : "2", "ContactName" : "Ted" }];
var sites = [{ "SiteId" : "1", "Location" : "MN" },{ "SiteId" : "2", "Location" : "FL" }];
I'm trying to write a method that converts either collection to a common type. An example of the above responses converted would look like this:
var convertedContacts = [{ "value" : "1", "text" : "Bob" },{ "value" : "2", "text" : "Ted" }];
var convertedSites = [{ "value" : "1", "text" : "MN" },{ "value" : "2", "text" : "FL" }];
So I'm trying to use the map function of jquery to facilitate this requirement. Although I can't seem to figure out how to dynamically query for the different property values that will exist depending on which json collection I'm passing into the function.
Here is an example of what I'm trying to do:
function ConvertResponse(arrayToConvert, text, value)
{
var a = $.map(arrayToConvert, function(m) {
return "{ \"text\" : "+eval("m."+text)+", \"value\" : "+eval("m."+value)+" }"
});
}
I also tried this:
function ConvertResponse(arrayToConvert, text, value)
{
var a = $.map(arrayToConvert, function(m) {
return "{ \"text\" : " + m.$(text) + ", \"value\" : " + m.$(value) + " }";
});
}
And this is how you would call it:
var convertedContacts = ConvertResponse(contacts, "ContactName", "ContactId");
var convertedSites = ConvertResponse(contacts, "Location", "SiteId");
Unfortunately this does not seem to work in the least.
Like this?
var contacts = [{ "ContactId" : "1", "ContactName" : "Bob" },{ "ContactId" : "2", "ContactName" : "Ted" }];
var sites = [{ "SiteId" : "1", "Location" : "MN" },{ "SiteId" : "2", "Location" : "FL" }];
function convertResponse(response, text, value) {
return $.map(response, function(it) {
return {
value: it[value],
text: it[text]
};
});
}
var convertedContacts = convertResponse(contacts, 'ContactId', 'ContactName');
var convertedSites = convertResponse(sites, 'SiteId', 'Location');