Knockout.js binding to json object memebr prefixed with # - json

I have converted some XML to Json using JSON.Net and am then binding to a view using Knockout.js.
The problem I have is that my XML attributes are represented in json, prefixed with an #,which is seen an illegal character in Knockout.js.
My view model has the following:
self.titles = ko.computed(function () {
var str = self.searchForText().toLowerCase();
return jsonString.AutoPolicy.Policy.filter(function (el) {
return el['#id'].toLowerCase().indexOf(str) == 0;
});
}, self);
and my html:
<div id="searchResultsDiv" class="sectionDiv">
<div data-bind="foreach: titles">
<div data-bind="text: #id, click: $parent.isSelected, event : { dblclick: $parent.openFileDblClick }"></div>
</div>
</div>
How do I bind to the attribute? Is there an escape key, or an alternative way to return from the view model?
EDIT
I have modified my view model to add an element that knockout can bind to:
// bind a list to json data **NEEDS TO VE ALL TITLES**
self.titles = ko.computed(function () {
var str = self.searchForText().toLowerCase();
jsonString.AutoPolicy.Policy['#id']
return jsonString.AutoPolicy.Policy.filter(function (el) {
el.id = el['#id'];
return el['#id'].toLowerCase().indexOf(str) == 0;
});
}, self);
This gives the desired results but is there a better way?
Thanks

Try something like this:
<div data-bind="text: $data['#id']"></div>

Related

React loop through json object and display data

I have a demo here
I have a simple json file that I'm importing and I would like to loop through and output the json data in a div
I'll probable want to pick out parts of the json but for now I just need to be able to output the json
Do I need to create an array from the json data and then map over that.
const showProductData = Object.keys(ProductData).map(function(key) {
return <div>{ProductData[key]}</div>;
});
const App = () => {
return (
<div>
<h2>JSON</h2>
{showProductData}
</div>
);
};
If you read the error message, Objects are not valid as a React Child. To modify your current code to just show the json, you will need to convert the object into a string.
const showProductData = Object.keys(ProductData).map(function(key) {
return <div>{JSON.stringify(ProductData[key])}</div>;
});
To be more concise with what we're accessing, we can instead use Object.values() instead:
const showProductData = Object.values(ProductData).map(function(value) {
return <div>{JSON.stringify(value)}</div>;
});
To further access specific points of the data, you can use dot notation to access primitive values:
const showProductData = Object.values(ProductData).map(function(value) {
return <div>Weight: {value.ProductWeight}</div>;
});
well, when i show ur a question, immediately i thought 'recursive solution' :)
so basically this is the code, I tried to explain it, feel free to dig into it
function getAllProps(obj) {
let value = obj;
// in case it is an object / array, which true, at any json file, at least at the beginning
if (typeof obj === "object") {
value = Object.keys(obj).map(key => {
// and then check again if the value of the 'key' is an object
// because we cant just out put object in react
if (typeof obj[key] === "object") {
// then out put the key name (property, 'ProductOne' for example)
// and call the function again since we know it is an object.
// basiclly the function will call it self again and again
// until the value will be different than 'object'
return (
<div key={key}>
<div style={{ marginLeft: 20 }}>
<strong> {key} </strong>
{getAllProps(obj[key])}
</div>
</div>
);
}
return (
<div key={key} style={{ marginLeft: 20 }}>
{key}: {obj[key]}
</div>
);
});
}
return value;
}
const products = getAllProps(ProductData);
const App = () => {
return (
<div>
<h2>JSON</h2>
{products}
</div>
);
};
actually, just check that link
read the comments, try to understand my 'recursive solution'

Typeahead each time user writes a certain word

I'm using the ui-bootstrap typeahead for when a user types to show all the variables available for him to write which are proprieties from an object which is loaded Ex: item.cost+item.quantity.
My question is I want the suggestions only to appear each time user types "item.", I've notice the typeahead only works for one word and at the beginning.
html
<div class="modal-body">
Add expression:
<textarea style="width: 568px;" ng-model="item.formula"
uib-typeahead="state for state in states "
typeahead-show-hint="true"
typeahead-on-select="item"
ng-change="eval(item.formula)">
</textarea>
<p><b>Result:</b> <br>
<div style="width: 100%">{{ans}}
</div>
</p>
</div>
controller
ctrl.controller('myController', ['$scope', function ($scope) {
$scope.imageShowModal = function (item) { //loads the object items
$scope.item = item;
$scope.states =Object.keys(item); //get the JSON keys from item object like cost,price,quantity,workflow...
};
$scope.eval = function (v) {
try {
$scope.ans = $scope.$eval(v);
} catch (e) {
}
};
You can use a custom filter in your uib-typeahead expression, ex: uib-typeahead="state for state in states | myCustomFilter:$viewValue"
A custom filter in your case might look like this:
angular.module('myApp')
.filter('myCustomFilter', function() {
return function(list, term) {
if (term.indexOf('item.') === -1)
return [];
var filteredList = [];
angular.forEach(list, function(value) {
if (value.indexOf(term) !== -1)
filteredList.push(value);
});
return filteredList;
}
});
See also: AngularJs UI typeahead match on leading characters

How to display the returned ajax Json results in HTML (using typescript)

The client (typescript) gets different results from the server, all are in json format. Sometimes a simple json result, sometimes complex nested jsons.
I need to present the results in a (very) simple html table.
function run(): void {
var url = this.selectedKnockoutDropList();
$.ajax(url, "GET").done(data => {
console.log(data);
*** here I want to do something like :
- open/embedd results.html
- fill a table with the json results parsed somehow
});
I tried $('#...).html(data) with no success.
You need to transform the JSON into meaningful HTML. This can be done in typescript, javascript. It can be done with jQuery it can be done using javascript templates such a handlebars. It can be done with SPA frameworks like Angular.
Please post an a sample of the returned JSON and I can update with a TypeScript example not using any toolsets or libs.
JSON is an object. To output it to the document you need to first convert it to a string:
$.ajax(url, "GET").done(data => {
$('#...).html(JSON.stringify(data));
}
However, if you know what kind of data you are getting back and want to output just parts of it, you'll need to loop the JSON. For example, if you had a JSON object like:
[
{name: "Joe", age: 32},
{name: "Suzy", age 23},
{name: "Tom", age 28}
]
You could output the names like this:
$.ajax(url, "GET").done(data => {
data.forEach(function(person) {
$(ul).append('<li>' + person.name + '</li>');
});
}
Martin and Robert - thanks for the quick replies. I took your advises and came with the following generic solution (which can display html text returned from the server or nested json object in a table) :
HTML:
<!--HTML-->
<div data-bind="visible: isHtml, html: htmlView"></div>
<!--SIMPLE JSON-->
<div data-bind="visible: isJson">
<table>
<thead>
<tr data-bind="foreach: columns">
<th data-bind="text: $data"></th>
</tr>
</thead>
<tbody data-bind="foreach: rows">
<tr data-bind="foreach: $parent.columns">
<td data-bind="text: $parent[$data]"></td>
</tr>
</tbody>
</table>
</div>
TS:
function run(): void {
this.isHtml(false);
this.isJson(false);
$.ajax(url, "GET").done(data => {
var jsonObj = data;
if (typeof (data) === "string") {
this.htmlView(data);
this.isHtml(true);
return;
}
if (data instanceof Array === false) {
jsonObj = [data];
}
this.columns([]);
this.rows([]);
for (var i = 0; i < jsonObj.length; i++) {
var item = jsonObj[i];
var newItem = {};
for (var key in item) {
if (i === 0)
this.columns.push(key);
if (typeof item[key] !== "object") {
newItem[key] = item[key];
} else {
for (var deeperKey in item[key]) {
this.columns.push(deeperKey);
newItem[deeperKey] = item[key][deeperKey];
}
}
}
this.rows.push(newItem);
}
this.isJson(true);
});
I used another stackoverflow post (which I can't find right now) for the nested rows. Obviously flatting the sub-rows is not what I want but it can easily be changed.
It's my first typescript/html program :)
Thanks Again!

AngularJS: Conditional Chaining with JSON Filter

I am trying to conditionally display certain fields of JSON objects using filters. Currently it displays something like this:
JSON Ouput:[
{ tag: "Reading", checked: true },
{ tag: "Writing", checked: false },
{ tag: "Homework", checked: true},
{ tag: "Groupwork", checked: false }
];
Desired output:
Reading, Homework
Where I would only display those fields in which checked == true.
HTML/AngularJS:
<div class="item">
<pre ng-bind="tagList | json"></pre>
</div>
where tagList is the javascript object above.
You can use something like:
angular.module('myApp',[]).filter('tagsjson', function(){
return function(items){
var arrayToReturn = [];
for (var i=0; i<items.length; i++){
if (items[i].checked) {
arrayToReturn.push(items[i].tag);
}
}
return arrayToReturn.join();
};
});
You can then use your filter as:
<div class="item">
<pre ng-bind="tagList | tagsjson"></pre>
</div>
Here is a plunker demonstrating the above
PS: you can name your filter json but this will override the built in filter, as you have in your code, not sure if this is what you want.

ng-init json Object

I use angularjs (ng-init) and I want to assign value to variable as jsonObj.
I try this one but it doesn't work.
ng-init="percentObj = [{ "value":40,"color":"#F5A623" },{ "value":60,"color":"#F5A623" }];
and another question
I want to assign value like
percentObj = [{ "value": parseInt($scope.projectData[0].value),"color":"#F5A623" },{ "value": parseInt($scope.projectData[0].value),"color":"#F5A623" }]
How to fix this problem??
Thx
You can use window object for set your json :
<script type="text/javascript">
window.data= {awesome:1};
</script>
view :
<div ng-controller="myCntrl" ng-init="init('data')">
controller :
function myCntrl($scope) {
$scope.init = function (settings) {
settings = window[settings];
console.log(settings.awesome); //1
};
}
Escape your quotes...
ng-init="percentObj = [{ \"value\":40,\"color\":\"#F5A623\" },{ \"value\":60,\"color\":\"#F5A623\" }];"
Try this...
<body ng-controller="TestController">
<div ng-init="Init()">
{{percentObj || json }}
</div>
</body>
$scope.Init = function()
{
$scope.percentObj = [{ "value":40,"color":"#F5A623" },{ "value":60,"color":"#F5A623" }]
}
Just have a JSON encoded string in some element's attribute and then catch that with Angular.
HTML
<div data-config="{title:'this is my title'}" my-directive></div>
AngularJS:
app.directive('myDirective', function () {
return {
restrict: 'A',
link: function (scope, element) {
// apply config from element's data-config attribute
scope.config = element.data('config');
// print out the data in console
console.log(scope.config);
}
};
});
Can be done without jQuery too, then the .data('config') part changes.
for second one, Please check the code below
var obj = {};
$scope.percentObj = [];
obj.value = parseInt($scope.projectData[0].value);
obj.color = "#F5A623";
$scope.percentObj.push(obj);