Jquery data-bind to a unordered list - javascript

Currently I'm adding data to my unordered list like this:
<ul id="mychats"></ul>
if (obj.request_type == 'client_information') {
$("#mychats").children().remove();
$.each(obj.clients_information, function (index, data) {
var li = "<li class='not_selected' id='" + data.chatid + "'>" + data.client_name;
if (data.status == 0) //Chat is unlocked
li += " <img class='chat_status' src='https://www.astro.ru.nl/lopes/_media/intra.png?w=&h=&cache=cache' />";
else
li += " <img class='chat_status' src='https://confluence.atlassian.com/download/attachments/686859081/page-restrictions-padlock-icon.png?api=v2' />";
li += "</li>";
$("#mychats").append(li);
});
}
This works as intended but I want to do it in a different way, I want to bind the ul with the data in obj.clients.informations directly.
Sample JSON data in obj:
{
"request_type": "client_information",
"clients_information": [{
"chatid": "0a9ef3c4-b34a-435f-b0c5-15bf415e1517",
"client_name": "awd",
"status": 0
},{
"chatid": "08a725c4-4fd1-471d-a507-4782f6bbc774",
"client_name": "awdaeqdaw",
"status": 0
}]
}
something like:
<ul id='mychats' data-bind='foreach: Clients' data-role='listview'>
<li data-binding='class: thisclass, id: chatid, text: client_name'></li>
</li>
With the specified code in jQuery to be able to bind it to the unordered list. I tried to search all over the net and I couldn't really find an example for jQuery.
Just this: http://jsfiddle.net/rniemeyer/4FdcY/ (i want something like this for my object)
Thanks all.

That example uses the knockoutjs library. The documentation on the website is spot on and is exactly what youre after.
Just parse your json in to an object and use knockout to bind the object to the markup.

Related

Filter JSON object with Array of selected checkbox

How i can filter my JSON object with array.
FIDDLE
This is an sample of my json object and code, i want to filter final render HTML by selected checkbox.
Thanks for your help
function init(arr){
var li = '';
$.each(jsn, function (key, value) {
if (arr.length == 0) {
li += '<li>' + jsn[key].name + '</li>';
}else{
$(arr).each(function (i, v) {
// this section must be filter "pack's" but i can't writ correct query
li += '<li>' + jsn[key].name + '</li>';
});
};
$('#container').html(li);
})
}
var CheckArr = new Array();
init(CheckArr);
$('#btnFilter').click(function(){
var CheckArr = new Array();
$('input[type=checkbox]').each(function () {
if ($(this).is(':checked')) {
CheckArr.push($(this).attr('value'))
}
});
init(CheckArr);
First of all, you have to verify length of array outside of init function. (for case when function is called for first time).Then, you need to iterate your checkboxes array and search every item in your json array(called jsn) to verify condition you need.
Here is solution:
$(document).ready(function(){
var jsn = [
{
"name":"pack01",
"caplessthan100mb":"False",
"cap100to500mb":"True",
"cap500mbto2g":"False",
"cap2gto10g":"False"
},
{
"name":"pack02",
"caplessthan100mb":"True",
"cap100to500mb":"False",
"cap500mbto2g":"False",
"cap2gto10g":"False"
},
{
"name":"pack03",
"caplessthan100mb":"False",
"cap100to500mb":"False",
"cap500mbto2g":"False",
"cap2gto10g":"True"
},
{
"name":"pack04",
"caplessthan100mb":"False",
"cap100to500mb":"False",
"cap500mbto2g":"True",
"cap2gto10g":"False"
},
{
"name":"pack05",
"caplessthan100mb":"False",
"cap100to500mb":"False",
"cap500mbto2g":"False",
"cap2gto10g":"True"
},
{
"name":"pack06",
"caplessthan100mb":"True",
"cap100to500mb":"False",
"cap500mbto2g":"False",
"cap2gto10g":"False"
},
{
"name":"pack07",
"caplessthan100mb":"False",
"cap100to500mb":"False",
"cap500mbto2g":"False",
"cap2gto10g":"True"
}
];
function init(arr){
var li = '';
if(arr.length==0)
{
$.each(jsn, function (key, value) {
li+= '<li>' + jsn[key].name + '</li>';
});
}
else{
$(arr).each(function (i, v) {
$.each(jsn, function (key, value) {
if(jsn[key][v]=="True")
li+= '<li>' + jsn[key].name + '</li>';
});
});
}
$('#container').html(li);
}
var CheckArr = new Array();
init(CheckArr);
$('#btnFilter').click(function(){
var CheckArr = new Array();
$('input[type=checkbox]').each(function () {
if ($(this).is(':checked')) {
CheckArr.push($(this).attr('value'))
}
});
init(CheckArr);
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li><input type="checkbox" value="caplessthan100mb">caplessthan100mb</li>
<li><input type="checkbox" value="cap100to500mb">cap100to500mb</li>
<li><input type="checkbox" value="cap500mbto2g">cap500mbto2g</li>
<li><input type="checkbox" value="cap2gto10g">cap2gto10g</li>
<li><input type="button" id="btnFilter" value="Filter"></li>
</ul>
<br />
<ul id="container">
</ul>
There are quite a few things in your code that could use improvement so I've taken the liberty of largely rewriting it (see jsFiddle link below).
1) First thing is in your data (jsn) you are using "False" and "True" instead of false and true. That'll make it hard to write your filter condition because true != "True".
2) It's quite hard to debug your code because the variable names aren't very meaningful. I'd highly recommend putting some energy into improving your variable names especially when code isn't working.
For example:
packsData instead of jsn
checkedBoxes instead of arr
3) If you try to filter within the .each() below you'll run into trouble when it matches more than one filter condition (it'll be displayed more than once).
$(arr).each(function (i, v) {
// this section must be filter "pack's" but i can't writ correct query
li += '<li>' + jsn[key].name + '</li>';
});
Here is a working jsFiddle

Blaze.getData(el) returns null unless data property is accessed

I am trying to make a list of re-orderable items in Meteor. My items have a info.order property which I change on click events. Why does the example below work until I comment out if the line below // ! ...?
If I comment out that line I get the error Cannot read property '_id' of null when data._id is referenced in the event handler.
This is minimal Meteor javascript:
Widget = new Mongo.Collection('widget');
if (Meteor.isClient) {
function moveUp (mongo_id) {
var clicked = Widget.findOne({_id: mongo_id});
var above = Widget.findOne({'info.order': clicked.info.order - 1});
if (above) {
Widget.update({_id: clicked._id}, {$inc: {"info.order": -1}});
Widget.update({_id: above._id}, {$inc: {"info.order": 1}});
}
}
Template.widget.helpers({
// Get list of widget to display and sort by latest first.
widget: function(data){
return Widget.find({}, {sort: {'info.order': 1}});
},
display: function(mongo_id, info) {
var html = '<div>';
html += '<div>' + info.label + '</div>';
html += '<div>Up</div>';
// ! IF NEXT LINE IS COMMENTED-OUT data == null IN EVENT HANDLER
html += '<div>' + info.order + '</div>';
html += '</div>';
return html;
}
});
Template.widget.events({
'click .js-moveup': function(e, tpl){
e.preventDefault();
var data = Blaze.getData(e.currentTarget);
moveUp(data._id);
}
});
} // end is MeteorClient
With this template:
<head></head>
<body>
{{> widget}}
</body>
<template name="widget">
<div class="container">
<h1>Widgets</h1>
{{#each widget}}
{{{display _id info}}}
{{/each}}
</div>
</template>
And this seed data:
Meteor.startup(function () {
if (Widget.find().count() === 0) {
[{info :{label: "first", order: 1}},
{info: {label: "second", order: 2}},
{info: {label: "third", order: 3}}
].forEach(function(w){
Widget.insert(w);
});
}
});
I've got an idea what's going on...
Meteor must compare the output of display() to it's previous value and only evaluate update the DOM if it has changed (or something similar). If I don't print out info.order the HTML of each widget is unchanged.
I tested this by replacing info.order with new Date() to add varying content that didn't reference the model and, sure enough, the widgets more as expected.
So, my take home message is that if you return raw HTML from display Meteor will try to do the write thing but won't always get it right.

Show JSON data based on checkbox choice

I'm wondering if it is possible to show specific JSON data, based on a choice made with a checkbox.
At this moment I have specific JSON data with peoples names, department, sex and internet usage.
I've managed to show this data by name, department and I drew a bar for the usage.
I've made two checkboxes that show this JSON data when checked. However at this particular moment they still show the same data. I need to find a way to sort it out, after trying certain things, it's kinda getting lost on me.
This is the code for getting the JSON data, showing it and the checkboxes + the code behind it:
JS :
$(document).ready(function() {
$('input[type="checkbox"]').click(function(){
if($(this).attr("value")=="female") {
$(".female").toggle();
}
if($(this).attr("value")=="male") {
$(".male").toggle();
}
});
});
ajax();
function ajax() {
$.ajax({
url:"wifi_data.json",
dataType:"json",
success: function(data) {
//if(data.geslacht == "man") {
$.each(data, function(index, item) {
$('#females').append('<br>Name: ' + data[index].voornaam + ' ' + data[index].achternaam +
'<br>Department: ' + data[index].afdeling +
'<br>Usage: ' + '<div style="width:'+
data[index].verbruik*0.001
+'px;height:10;border:2px solid ; background-color:red;"></div>' +
'<div style="'+ '<br>Sex: ' +
data[index].geslacht +'"></div>' );
});
//}
//if(data.gelsacht =="vrouw") {
$.each(data, function(index, item)
{
$('#males').append('<br>Name: ' + data[index].voornaam + ' ' + data[index].achternaam +
'<br>Department: ' + data[index].afdeling +
"<br>Usage: " + '<div style="width:'+
data[index].verbruik*0.001
+'px;height:10;border:2px solid ; background-color:red"></div>' );
});
//}
}
})
}
HTML :
<div>
<label><input type="checkbox" name="colorCheckbox" value="female"> Show Female Members</label>
<br>
<label><input type="checkbox" name="colorCheckbox" value="male"> Show Male Members</label>
</div>
<div class="female box">
<div id="females"></div>
</div>
<div class="male box">
<div id="males"></div>
</div>
What I've tried to do here with the commented parts of the code (and some code that is removed) is to only append males when "geslacht"(sex) is man(male) or vrouw(female).
I've also tried to append the sex and to then put it in a div and hide it. In order to maybe check if male or female is checked, then show the hidden div's with all the men or females in it.
My issue is that I'm having a huge brain fart on the part how to check what is checked, and then only gather the males or females from the JSON file based on choice.
The JSON looks like this:
{
"46": {
"voornaam": "Sergio",
"achternaam": "Bloemenouw",
"verbruik": "100000",
"afdeling": "FHACI",
"geslacht": "man",
"verbruikPercentage": "18.2%"
},
"25": {
"voornaam": "Chayenne",
"achternaam": "Aalberink",
"verbruik": "200000",
"afdeling": "FHEHT",
"geslacht": "vrouw",
"verbruikPercentage": "36.4%"
},
and so on...
Hopefully someone can steer me into the correct direction.
I think the most important thing I need to figure out is how to only show either the females or the males including their name, usage("verbruikPercentage") and department("afdeling")
Your question contains two problems. One is to separate data into male and female parts, and the other one is about showing/hiding the elements.
For the data separation, you need to do the if statement for each data item, since it is the item that contains the geslacht property.
$.each(data, function(index, item) {
var target = item.geslacht === 'man' ? $('#males') : $('#females');
target.append('<br>Name: ' + data[index].voornaam + ' ' + data[index].achternaam +
'<br>Department: ' + data[index].afdeling +
'<br>Usage: ' + '<div style="width:'+ data[index].verbruik*0.001 +
'px;height:10;border:2px solid ; background-color:red;"></div>' +
'<div style="'+ '<br>Sex: ' + data[index].geslacht +'"></div>');
});
For the toggling, I didn't see anything wrong for now. You can focus on the data processing part for now, and do more debugging on it later.
Your if condition should be inside $.each() loop as follows:
$.each(data, function(index, item) {
if(item.geslacht == "man") {
}
else if(item.geslacht == "vrouw")
{
}
})

Fetching user data from JSON to an expanded select box and displaying the value when option selected

I want to get the json data from a file which has a nested JSON objects, like this.
{
"userId": "1",
"data": {
"id": 1,
"name" : "Lorem Ipsum",
"value" : "Salut Dolor"
}
}
And once I get it I want to create a select object with the Id as the displayed text and append it to a div.
Once the select object is created, I also want to automatically open the select options when the page gets loaded.
Once a value is selected from there, I want to display the name that is present in the json for that id.
I'm able to fetch only the UserId from this code, how will i meet the requirements?
$.ajax({
url: 'obj.json',
dataType: 'JSON',
success: function (data) {
var items = [];
$.each(data, function (key, value) {
items.push('<option id="' + key + '">' + value + '</option>');
});
$('<select/>', {
class: 'intrest-list',
html: items.join('')
}).appendTo('body');
},
statusCode: {
404: function () {
alert("There was a problem");
}
}
});
what is this good for? do you want to fetch more then 1 user in the future?
you could so something like this:
//user.json
[{id:1,name:'xxxx'},...]
....
for(var i = 0;i<data.length;i++){
items.push('<option id="' + data[i].id + '">' + data[i].name+'</option>');
}
...
or in your case, you can access it directly with:
data.data.id
data.data.name
data.data.value
would get you the right values
Solved it myself. Although i came up with an alternative to display the list of select elements as:
<select name="" id="details" size="2"></select>
also created a container to post the values of the JSON object selected from the select box:
<div id="container"></div>
and the jQuery part where the magic happens goes like this:
$.getJSON('obj.json', function(obj) {
$.each(obj, function(key, value) {
$("#details").append('<option>'+ value.name +'</option>')
});
$( "select" ).change(function () {
var value = $( "select option:selected").val();
$.each(obj, function(key, val) {
if (val.name == value) {
$("#container").html(val.value);
}
});
});
});
This pretty much made the select box as a list of items and the value.name selected in it makes the value.value visible in the div container.

AngularJS directive that appends HTML elements to existing element

I have an AngularJS, JS, JQ, HTML5 web app, which is capable of sending different HTTP methods to our project's RESTful Web Service and receiving responses in JSON.
It looks like this:
What I want is to create an AngularJS directive, which could accept JSON object and create an <li> for every JSON property it finds. If property itself is an object - the function should be called recursively.
Basically, I search a way to parse a JSON object to HTML elements in a such way that following JSON:
{
"title": "1",
"version": "1",
"prop" : {
"a" : "10",
"b" : "20",
"obj" : {
"nestedObj" : {
"c" : "30"
}
}
}
}
Would be transfrormed into following html:
<ul>
<li>title : 1</li>
<li>version : 1</li>
<li>
prop :
<ul>
<li>a: 10</li>
<li>b: 20</li>
<li>
obj :
<ul>
<li>
nestedObj :
<ul>
<li>c : 30</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
Does anyone know how to achieve this using AngularJS directives? Every useful answer is highly appreciated and evaluated.
Thank you.
I tried this by recursivly include a directive. But this seems be really ugly.
My solution is just like the plain old html generated out of a recursive method and append as element:
//recursivly generate the object output
scope.printObject = function (obj, content) {
content = "<ul>";
for (var i in obj) {
if (angular.isObject(obj[i])) {
content += "<li>"+i+""+scope.printObject(obj[i])+"</li>";
} else {
content += "<li>" + i + ":" + obj[i] + "</li>";
}
}
content+="</ul>";
return content;
};
Full working code here:
http://jsfiddle.net/zh5Vf/1/
It has little to do with Angular (it's plain old JS), but for the fun of it, here is a directive that does what you want:
(It is a bit more lengthy in order to properly format the HTML code (indent) and support custom initial indentation.)
app.directive('ulFromJson', function () {
var indentationStep = ' ';
function createUL(ulData, indentation) {
indentation = indentation || '';
var tmpl = ['', '<ul>'].join('\n' + indentation);
for (var key in ulData) {
tmpl += createLI(key, ulData[key], indentation + indentationStep);
}
tmpl = [tmpl, '</ul>'].join('\n' + indentation);
return tmpl;
}
function createLI(key, value, indentation) {
indentation = indentation || '';
var tmpl = '';
if (angular.isObject(value)) {
var newIndentation = indentation + indentationStep;
tmpl += '\n' + indentation + '<li>' +
'\n' + newIndentation + key + ' : ' +
createUL(value, newIndentation) +
'\n' + indentation + '</li>';
} else {
tmpl += '\n' + indentation + '<li>' + key +
' : ' + value + '</li>';
}
return tmpl;
}
return {
restrict: 'A',
scope: {
data: '='
},
link: function postLink(scope, elem, attrs) {
scope.$watch('data', function (newValue, oldValue) {
if (newValue === oldValue) { return; }
elem.html(createUL(scope.data));
});
elem.html(createUL(scope.data));
}
};
});
And then use it like this:
<div id="output" ul-from-json data="data"></div>
See, also, this short demo.

Categories