At work I'm just starting out with JavaScript, MVVM, and Kendo's JS framework, all at once, and I have a fairly simple problem.
I've created a View Model that allows Superheroes to be registered.
The JSBin I'm working in: http://jsbin.com/gewu/3/edit?html,js,output
Here's the HTML(view):
<div id="view">
Superhero: <input data-bind="value: name" /><br/>
Superpower: <input data-bind="value:power"type="text">
<label for="">from Earth?<input type="checkbox" data-bind="checked:fromEarth"></label>
<button data-bind="click: registerHero" >Display User Info</button>
<div id="array-display"></div>
<p>Entries: <span data-bind="text: knownHeroes.length"></span></p>
</div>
And here's the JS (viewModel):
var viewModel = kendo.observable({
knownHeroes : [],
name: "Hulk",
power:"Stength",
fromEarth: true,
registerHero: function() {
var name = this.get("name");
var power = this.get("power");
var fromEarth = this.get("fromEarth");
this.knownHeroes.push({"name":name,"power":power,"fromEarth":fromEarth});
}
});
kendo.bind($("#view"), viewModel);
Now, I'm trying to get the View to loop through and display the array of knownHeroes. But it won't render anything. I know the data is being pushed to the array, because I can see the array.length increasing, and I can look up specific values in the array. I'm assuming the problem has to do with how I'm referencing the array in the view. But I'm not sure. Here's the template I've written:
HTML:
<script id="registry-view" type="text/x-kendo-template">
<ul>
# for (var i=0; i < knownHeroes.length; i++) { #
<li>
<ul>
<li>#= knownHeroes[i].name #</li>
<li>#= knownHeroes[i].power #</li>
<li>#= knownHeroes[i].fromEarth #</li>
</ul>
</li>
# } #
</ul>
</script>
<script type="text/javascript">
var template = kendo.template($("#registry-view").html());
$("#array-display").html(template); //Append the result
</script>
You have got some mistakes.
First of all you got script wrote in html portion of this jsbin as well as in javascript section. Html part executes first so the viewModel isn't defined yet (check console for errors)
Also the object you pass to the template is stored always in "data" variable.
Last mistake is when using your desing, anytime you add any new data row, whole template needs to be reloaded (including all previously added data rows)
I corrected some of your mistakes in following jsbin: http://jsbin.com/jomemuko/1/edit (actually you need to hit the Run with JS button to make it work - some script loading issue I don't have time for)
Ideally you should use a listView widget and assign it a template for only one item. Also in your viewModel you should create a kendo dataSource and pass it as an option to newly created listView. Then in the viewModel you should refine your registerHero function to make it add the hero to the dataSource. Widget should automatically refresh.
Hope it helps
Related
I'm able to display one row into myField but i want to loop through all rows.
I want to display all names in a formatted text in html. i think something with for-each in my HTML View, but im really stuck here.
My JSON from couchDB looks like this:
{"total_rows":8,"offset":0,"rows":[
{"id":"f1abbf3ccb0f15d6a66f7eadab003f53","key":"AccessBareBoneApp","value":{"Properties":{"Properties":[]},"Implements":{"Interfaces":[{"TypeName":"ITSR2.Bricks.Access.IAccessBareBoneBrick"},{"TypeName":"ITSR2.Bricks.Access.IAccessAppBrick"}]},"Name":"AccessBareBoneApp","Description":"","TypeName":"ITSR2.Bricks.Access.AccessBareBoneApp","AssemblyName":"ITSR2.Bricks.MSOffice, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null","Obsolete":false}},
My main.js file:
function ViewModel() {
var self = this;
self.myfield = ko.observableArray([]);
}
var db = new PouchDB('http://localhost:5984/helloworld');
var vm = new ViewModel();
db.query("bricksetup/docs").then(function(result) {
var data = result;
console.log(data);
data.rows.forEach(function(row){
vm.data.push(row.value)
// vm.myfield(data.rows[3].value.Name);
// vm.myfield2(data.rows[2].value.Name);
})
vm.myfield(data.rows[3].value.Name);
});
ko.applyBindings(vm);
My index.html:
<h3>Brick Infos</h3>
<div data-bind="">
<p>
<b>Name:</b>
<span data-bind="text:myfield"></span>
<b>Description:</b>
<span data-bind=></span>
<b>TypeName:</b>
<span data-bind=></span>
<b>AssemblyName</b>
<span data-bind=></span>
<b>Obsolete</b>
<span data-bind=></span>
</p>
<p data-bind=>
<b>Name:</b>
<span data-bind=></span> |
<b>Validation Type:</b>
<span data-bind=></span><br>
</p>
</div>
You just need to pass the data.rows to your variable myField like this vm.myfield(data.rows); . Place it under your console.log and remove the forEach Loop.
And on Index.html:
<div data-bind="foreach:myfield">
<span data-bind="text:value.Name"></span>
</div
Hope this helps
You need to do more work on the Javascript side and assuming there is going to be more than one row then assign that to a ko.observableArray. Is that what self.myfield is for?
Assuming yes, then set up the self.myfield using something like self.myfield(data.rows). nice and simple and no need for all that pushing!
On the HTML side, for each row you need a data-bind e.g.
<h3>Brick Infos</h3>
<div data-bind="foreach: self.myfield">
I think this will work - I use ES6 Javascript so I don't have to use self = this, I would just use foreach: myfield
The rest of the html is not using proper data-bind syntax. Each field would need something like <p><span class="title">Field Title</span><span class=text data-bind="text: data.fieldName"></span></p>
Then create a css class to highlight the title and replace Field Title with whatever you want to appear to the user as the title of the field, and replace Fieldname with the relevant fieldname e.g. Name, Description, TypeName etc.
Note items which which have multiple values possible such as Implements.Interfaces use data-bind=:foreach data.Implements.Interfaces to repeat those items if needed on the page.
You're pushing into vm.data, but the observableArray field is myfield. Then you're setting the value of the observableArray to the Name field of one data item. That's a very confused approach.
It looks like your query is going to come back with a result that contains rows, which are (more or less) what you want in your array.
db.query("bricksetup/docs").then(function(result) {
vm.myfield(result.rows);
});
It also looks like each row has a value object, and the fields you're interested in are inside that.
<h3>Brick Infos</h3>
<div data-bind="foreach:myfield">
<b>Name:</b>
<span data-bind="text:value.Name"></span>
</div>
This should get you started with the fewest lines of code. You'll probably want to re-map the rows to just put the value object into myfield.
I have a setup that I have replicated here:
http://codepen.io/anon/pen/EjrPbV
<div id="fac_content">
<input class="search" placeholder="Search">
<ul class = "list" id="fac_list" style="display: block;">
<li>
<p class="fac_name">CheckOneTwo</p>
</li>
<p></p>
<li>
<p class="fac_name">FiveThreeOne</p>
</li>
<p></p>
</ul>
</div>
<script src="//cdnjs.cloudflare.com/ajax/libs/list.js/1.1.1/list.min.js"></script>
<script>
var options = {
valueNames: [ 'fac_name']
};
var userList = new List('fac_content', options);
</script>
The problem is that when I am implementing it in my website, when I enter in the search field, everything inside of <ul></ul> gets deleted, no matter the character I input. I realize that there must be something else that is causing this in my code, the question is, what could cause code to be deleted? Note that the list elements are being generated on startup in my website using AJAX and the innerHTML property.
Note, for me, I get an error:
Uncaught TypeError: Cannot read property 'values' of undefined
Same answer as found here: Why are some rows disappearing when I sort or filter listjs table
(Referencing answer by brymcbride)
Issue was that I was making the list in listjs before the AJAX call. When I put the code right after the call was being made, everything worked out perfectly!
hi it's a cordova app that use devexpress framework based on knockout i need to set visible only one item in a list
the item should correspond to the param.id or this
id_agenzia:ko.observable(params.id),
i've tryed with jquery (setting the id "#"+$data.id_agenzia visible if == id_agenzia ) but if i integrate it doesn't work
the goal is to do something like this
if i put this line it ignores
how is the right way to set visible only the div that corresponds to $data.id_agenzia is valid for $data.id_agenzia==id_agenzia ?
thank you for help
this is the js code with jsfiddle code added
self.selected_id_agenzia = ko.observable('two');
self.jsonLista = ko.observableArray([
{id_agenzia:ko.observable('one'), nome:'N1'},
{id_agenzia:ko.observable('two'), nome:'N2'}
noDataLabel: noDataLabel,
this is the html code with jsfiddle code added
<div class="list-indentation" data-bind="foreach:jsonLista" style="padding-bottom:60px;">
<div id="$data.id_agenzia" data-bind="visible: id_agenzia()==selected_id_agenzia()">
<div class="agency-description-box" >
<span data-bind="text: $data.id_agenzia" class="agency-name"></span>
<span data-bind="text: $data.nome" class="agency-name"></span>
</div>
</div>
</div>
I think I misunderstood what you were doing with the variables. I have made a simplified fiddle to do what I think you want. To make it work:
I assumed a dxList was more or less like a foreach
I changed the name of the outer id_agenzia to selected_id_agenzia, as I was not able to get the comparison to work using $data and $root to distinguish them
I made both items ko.observables, and used the function call on each in the comparison
</div>
The code is all at the fiddle:
http://jsfiddle.net/3ktq4b9s/
I am trying to update or replace a list and keep the styles that were present before the update. Reading form the jQuerymoble website it says that the refresh() method call only works on new nodes. I am using the .html call to update the list and not .append. I am not sure if that is where I am having problems but the refresh call is not working in any case. My new list does not have the correct styles. I am using .html because many nodes are removed/added at the same time so append would not really work in my case.
Sample Code:
<script>
$(document).ready(function(){
$("#quicksearch").keyup(function() {
$.getJSON(search,function(data){
newlistcode= data //formatted correctly for a new list
$(“ul”).html(newlistcode);
$(“ul”).listview(‘refresh’);
});
});
});
</script>
<div data-demo-html="true">
<ul data-role="listview" class="list" id="listview1">
<li>test</li>
</ul>
</div>
Change
$(“#listview1”).html(newlistcode);
$(“listview1”).listview(‘refresh’);
to
$(“#listview1”).append(newlistcode);
$(“#listview1”).listview(‘refresh’);
Where
newlistcode = '<li><a>content</a></li>';
I'm trying to make a cross platform mobile application using jQuery Mobile.
I have a JSON string that displays information about a specific object (check it out here: http://app.calvaryccm.com/mobile/web/teachings/json?callback=?) and I want it to turn it into a list view that connects to a single item view. The problem is, the listview isn't displaying like a list at all. It is almost like HTML without CSS. Check it out here: http://mbeta.calvaryccm.com/#teachings
This is the Javascript for parsing the JSON string:
<!-- Getting Teaching Data -->
<script type="text/javascript">
$(document).ready(function () {
$.getJSON("http://app.calvaryccm.com/mobile/web/teachings/json?callback=?",
function (data) {
//remove any characters from the query that might be unsafe to use as an ID for a page
//data.pageId = data.MessageNumber.replace(/[^\w]/, "");
//Feed the data to the template and add the new page to the body.
var res = $("#teachingTemplate").tmpl(data); //.appendTo(document.body);
$("#teachings").append(res);
//Grab a reference to that shiny new page
//var newpage = $("#" + data.pageId);
});
});
//Makes date readable
function GetDate(jsonDate) {
var value = new Date(parseInt(jsonDate.substr(6)));
return value.getMonth() + 1 + "/" + value.getDate() + "/" + value.getFullYear();
}
This is supposed to be the list view:
<script id="teachingTemplate" type="text/x-jquery-tmpl">
<div id="${MessageNumber}">
<div data-role="header">
<a data-icon="arrow-l" href="#" data-rel="back">Back</a>
<h1>${Title}</h1>
</div>
<div data-role="content">
<div class="teachingsForm">
<ul data-role="listview">
<li><a href="singleTeachingView" class="tableImage">
<img src="" alt=""/>
<h3>${Title}</h3>
<p>${Speaker} - ${GetDate(MessageDate)} - ${MessageNumber} {{if Book != null}} - ${Book.BookName} ${ChapterVerse}{{/if}}</p>
</a>
</li>
</ul>
</div>
</div>
<div data-role="footer">
<h4>2011 Calvary Chapel Melbourne</h4>
</div>
I cannot figure out why my listview isn't displaying right. If you want to see it in action look here: http://mbeta.calvaryccm.com/#teachings . I need help getting my listview to display right and direct to the right page.
It looks exactly like what your template says it should look like. Note that each of your <ul> elements only has one <li> element in it.
Your template starts off with an outer <div>, and then there's a "header" <div> with the <h1> title. Then there's the "content" <div>, and ultimately the <ul>, and finally the "footer". That's what your result page looks like. If you want to do some sort of iteration, well, you'll have to explicitly do that in your template, because otherwise the template code will assume you just want it to re-apply the template to each object in the array you pass it.
There's nothing wrong with the "JSON parsing". Note that in your JSON, there's no need to quote "/" characters with "\" and in fact (though it doesn't matter for JSONP) it's not valid JSON.
edit — OK so now that I've pulled my head out from wherever it was I think I see what you're doing. The problem may be that you just need to call
$.mobile.changePage();
at the end of your JSONP callback function. However I note that your "$.mobile" doesn't have a "changePage()" function ... I don't know what that means. You're using a pretty old version of jQuery too.