jsviews
Interactive data-driven views, MVVM and MVP, built on top of JsRender templates
JsRender/JsViews
I have very nested data, so I added a {{scope variable}}...{{/scope}}
tag, which does nothing but changing the scope:
scope: function (newScope) {
return this.tagCtx.render(newScope);
}
This works so far, but this sample code has an issue in the onAfterChange
, which I use to push data back to the server.
In the initializer:
data.Foo.Bar.TheObject = new MyObject('Foo'); // has "Name" property set to "Foo"
In the template:
{{scope Foo.Bar.TheObject}}
<input type="text" data-link="Name" />
{{/scope}}
It will display "Foo" correctly, but when I change it, in the onAfterChange
I get the data
object instead of TheObject
. Can I add something to {{scope}}
to achieve a scope change for the onAfterChange
?
(The {{for}}
tag has this behavior but I can't loop over a single object.)
Source: (StackOverflow)
How can I loop a nested json like this below with jsrender/ jsviews?
var data = {
nested: {
page: {
type: "X",
items: {
"0":{"title":"page - hello"},
"1":{"title":"page - world"}
}
},
post: {
type: "Y",
items: {
"0":{"title":"post - hello"},
"1":{"title":"post - world"}
}
}
}
};
template,
{{for nested}}
<div>
<h1>Type: {{ :type }}</h1>
{{for items}}
<p>Title: {{:title}} </p>
{{/for}}
</div>
{{/for}}
result,
Type: {{ :type }}
What I am after,
Type: X
Title - page - hello
Title - page - World
Type: Y
Title: post - hello
Title: post - World
Source: (StackOverflow)
I have the following piece of code which has a bunch of notes but I only want to show this div if the selectedNotes is not null. I used the length attribute which has worked fine.
<div id="notesContainer" data-link="visible{:selectedNotes.length != 0}">
<ul id="notes">
{^{if selectedNotes != null}}
{^{for selectedNotes}}
<li>{^{:Value}}</li>
{{/for}}
{{/if}}
</ul>
<p>There are <span data-link="{:selectedNotes.length}"></span> notes so far...</p>
<a id="addNote" data-toggle="modal" rel='nofollow' href="#addNoteModal" class="btn btn-primary">Add note</a>
</div>
My problem is the span within the div shows an error regardless of whether the selectedNotes object is set. The error is "data.selectedNotes is null". Why is that? If it's within the div shouldn't it be working correctly by not showing the paragraph?
I have put the code in this fiddle: http://jsfiddle.net/armydee/Z9wBJ/
Source: (StackOverflow)
Right now, I'm binding events to the parent element of my custom tag's rendered content, then using classes to target the event onto the element which my custom tag actually renders. I feel this is likely to cause strange bugs. For instance, if anyone on my team places two custom tags using the same targeting-classes under the same immediate parent element, it would cause multiple events to fire, associated with the wrong elements.
Here's a sample of the code I'm using now:
$.views.tags({
toggleProp: {
template: '<span class="toggle">{{include tmpl=#content/}}</span>',
onAfterLink: function () {
var prop = this.tagCtx.view.data;
$(this.parentElem).on('click', '.toggle', function () {
prop.value(!prop.value());
});
},
onDispose: function () {
$(this.parentElem).off('click', '.toggle');
}
}
// ... other custom tags simply follow the same pattern ...
});
By the time we hit onAfterLink
, is there any reliable way to access the rendered DOM Element (or DOM Elements) corresponding to the custom tag itself? With no risk of hitting the wrong element by mistake? I understand that the custom tag may be text without an HTML Element, but it would still be a text node, right? (Could I even bind events to text nodes?)
In other places, and using (far) older versions of JsViews, I've bound events after the render using (sometimes a lot of) targeting logic built into the rendered elements as data-
attributes. Not only is this a far more fragile method than I like for accessing the rendered data, it would be incredibly risky and convoluted to try to apply this approach to some of our deeply-nested-and-collection-ridden templates.
I also don't like needing to insert a span
with my custom tag, just so I can apply classes to it, but if it's still necessary for the event, I'll cope.
I ask, then, what is a safe, modular way to bind events to the DOM so that I also have access to the data rendered directly against those elements?
Edit: As an additional concern, using onAfterLink
won't let me bind events to non-data-linked rendered content. This may be part of the design intent of JsViews vs pure JsRender, but I don't yet understand why that would be the case.
Source: (StackOverflow)
I've created a complex template using JsRender with a bunch of nested tables. Now I'm transitioning to using JsViews so that I can take advantage of data-binding+incremental DOM updates (so that I don't have to re-render the entire template). However, I get an interesting error:

This problem goes away if I make sure each tr is within any of thead, tbody, or tfoot, as long as the tr is not a direct child of table. So my question is this: where did this design decision for JsViews come from? Why impose this constraint?
Thanks in advance.
jsviews.js:83 badParent = {tr: "table"}
Source: (StackOverflow)
I am reading up this page http://www.jsviews.com/#linked-elem-syntax and testing a bit.
- I like to start with this ..
Notice that the <input data-link="name trigger=true"/>
tag
automatically has two-way data-binding.
Am I correct to say that if removing "trigger=true" will make the one-way binding? Or, Is it still two-way binding?
The only difference that I found for having "trigger=true" and not having "trigger=true" is that you will get the update on property-changed event if you have "trigger=true". otherwise, you will see get the update on lost-focus event.
- I am also confused about having ":" before at the end.
Notice the full syntax for the has an additional ':' before
the '}' at the end. It corresponds to the two-way data binding.
Does it mean that having ":" at the end has the same effect as having "trigger=true"?
But i tried the code below and it doesn't work like the code that has "trigger=true".
<input data-link="{:name:}"/>
Source: (StackOverflow)
This is My Code below
<script type="text/javascript">
var test1 = {
"type" : "success",
"code" : "600",
"data" : [ ]
};
var template = $.templates("#template");
var htmlOutput = template.render(test1);
$("#billListBox").html(htmlOutput);
function billButtonOnClick(searchBillId,isComeFromBillClick,billDiv){
console.log(searchBillId);
console.log(isComeFromBillClick);
console.log(billDiv);
}
</script>
<div id="billListBox"></div>
I want to check data is empty or null in jsrender? how to check ?
Source: (StackOverflow)
I am using jsView (v1.0.0-alpha)
I am having an issue in getting the data from the view. Let's I have the following code. (I created a simplified version here http://jsfiddle.net/j5oc0svg/ ) I am trying to get the data object that I bind to the view earlier by using the place holder name. It's always return 'undertified'. If I called $.view().views then I can see the view and the data that I bind earlier.
How can I get the data that bind to the view by using the placeholder or (view name?)?
Thanks in advance.
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery.js"></script>
<base rel='nofollow' href="http://www.jsviews.com/samples/"/>
<link rel='nofollow' href="samples.css" rel="stylesheet"/>
<script src="../download/jsviews.js"></script>
</head>
<body>
<table><tbody id="peopleList"></tbody></table>
<script id="personTmpl" type="text/x-jsrender">
<tr>
<td>Name</td>
<td>{{:name}}</td>
</tr>
</script>
<script>
$.ajax({
url: "http://localhost:4728/api/People/,
dataType: 'json'
}).done(function (data) {
if (data!= null) {
var template = $.templates("#personTmpl");
template.link("#peopleList", data);
}
}).fail(function (exception) {
console.log(exception.message);
});
// Let's say this code is in button on click or push subscriber
hub_proxy.client.UpdateSomething = function (someArgs) {
var data = $.view('#peopleList').data; //underfined.
}
</script>
</body>
</html>
Source: (StackOverflow)
A "working" copy of what I'm trying to do is below, I simply want to be able to add or edit data in the array but I have to do things like $('#examQuestion').val()
.
That seems more like a hack.
I assume there is an easy solution to this with data-linking, I'm just not sure how to fix this.
Here is the code in jsFiddle
<!doctype html>
<html class="no-js" lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>test</title>
</head>
<body>
<div id="main"></div>
<script id="newTmpl" type="text/x-jsrender">
<table width="100%">
<thead>
<th>Question</th>
<th>Questoin Type</th>
<th>Actions</th>
</thead>
<tbody>
<tr>
<td>
<textarea placeholder="Exam Question" rows="10" id="examQuestion" name="examQuestion" cols="50"></textarea>
</td>
<td>
<select id="examQuestionType" name="examQuestionType"><option value="0" selected="selected">-- Please select question type --</option><option value="1">Radio Button</option><option value="2">Checkbox</option><option value="3">Textarea</option><option value="4">Text</option></select>
</td>
<td>
<button class="addOrUpdateQuestion" type="button">Add / update</button>
</td>
</tr>
{^{for questions}}
<tr>
<td>
{{:question}}
</td>
<td>
{{:typeName}}
</td>
<td>
<button class="editQuestion" type="button">Edit</button>
</td>
</tr>
{{/for}}
</tbody>
</table>
</script>
<script src="jquery.js"></script>
<script src="jsviews.min.js"></script>
<script>
$(function() {
var question = [];
var app = {
name: '',
description: '',
selectedQuestionId: -1,
questions: question
};
var tmpl = $.templates("#newTmpl");
tmpl.link("#main", app);
$('#main').on('click', '.editQuestion', function() {
var tmpData = $.view(this).data
app.selectedQuestionId = $.view(this).index;
$('#examQuestion').val(tmpData.question);
$('#examQuestionType').val(tmpData.type);
});
$('#main').on('click', '.addOrUpdateQuestion', function() {
if (app.selectedQuestionId == -1) {
$.observable(question).insert({
question: $('#examQuestion').val(),
type: $('#examQuestionType').val(),
typeName: $('#examQuestionType').find(':selected').text()
});
} else {
var tmpItem = app.questions[app.selectedQuestionId];
tmpItem.question = $('#examQuestion').val();
tmpItem.type = $('#examQuestionType').val();
tmpItem.typeName = $('#examQuestionType').find(':selected').text();
app.questions[app.selectedQuestionId] = tmpItem;
$.observable(question).refresh(question);
}
});
});
</script>
</body>
</html>
Source: (StackOverflow)
I am experimenting with Boris Moore's jsrender/jsviews libraries and am using the current version at the moment (commit 26). (I realize the API is in flux but would like to practice using it)
I've looked at the demos here:
http://borismoore.github.com/jsviews/demos/index.html
But I am having trouble determining the data-link
syntax. In some of the demos the syntax is data-link="{:FirstName:}
I don't understand why the 2 colons. I assume the 1st colon means no HTML encoding would be done, but have no idea about the 2nd one.
In other places I see syntax like data-link="address.street"
Here there are no curly braces or colons at all. I wonder when you need them and when you don't. Also I don't follow how you would specify if you want one-way or two-way binding. Or if you wanted binding to trigger in response to a key press instead of blur.
Here's an example I'd like to setup properly:
<div id="form">
<p>
<label>First Name</label>
<input type="text" name="FirstName" data-link="FirstName"/>
</p>
<p>
<label>Last Name</label>
<input type="text" name="LastName" data-link="LastName"/>
</p>
<p>
<label>Full Name</label>
<input type="text" data-link="FirstName + ' ' + LastName"/>
</p>
<p>
<label>Gender</label>
<select name="Gender">
<option value="U">Unknown</option>
<option value="M">Male</option>
<option value="F">Female</option>
</select>
</p>
</div>
<script>
var data =
{
FirstName: "Bill",
LastName: "Willis",
Gender: "M"
};
$("#form").link(true, data); //What is the 1st parameter (true) about?
</script>
I don't know how to bind to the select control.
I'd appreciate any explanation of how this should be done.
Source: (StackOverflow)
Below is the example where #parent.data
works and the first title can be changed. But when #parent.data
is replaced with ~root
, test2
tag is not rendered.
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="js/jquery-1.9.1.min.js" type="text/javascript"></script>
<script src="js/jsrender.js" type="text/javascript"></script>
<script src="js/jquery.observable.js" type="text/javascript"></script>
<script src="js/jquery.views.js" type="text/javascript"></script>
<script id="test1Template" type="text/x-jsrender">
<div>{^{>title}}{{:content}}</div>
{{test2}}
<h1>{^{>#parent.data.title}}</h1>
{{/test2}}
</script>
<script id="myTemplate" type="text/x-jsrender">
{^{test1 title='Test Title 1'}}
{^{test1 title='Test Title 2'}}
{{/test1}}
{{/test1}}
</script>
<script type="text/javascript">
$.views.tags({
test1: function () {
this.tagCtx.props.content = this.tagCtx.render();
return $.templates.test1.render(this.tagCtx.props, undefined, this.tagCtx.view);
},
test2: function () {
return this.tagCtx.render();
}
});
$.templates({myTemplate: "#myTemplate",
test1: "#test1Template"
});
$(function () {
$.link.myTemplate('#container', {});
$('#editTitle').click(function () {
$.observable($.view('#container > div:first').data).setProperty('title', prompt());
});
});
</script>
</head>
<body>
<span id="editTitle">EditTitle</span>
<div id="container"></div>
</body>
</html>
Source: (StackOverflow)
I am writing a small javascript game... to set in-game time, I have variable that holds the current in-game date and time, I want to display this date and every seconds, increase that date with hours.
I am using JSViews for the databinding and it works well in the application except for that date and I don't understand !! I have created a JSFiddle that represents the idea:
http://jsfiddle.net/ClaudeVernier/w8cwkarr/5/
try {
var tmplDates = $.templates("#tmplDates");
tmplDates.link("#gameSet", model);
gameLoop();
}
catch(e) {
alert(e);
}
I have a data model with a date and an integer.
I have a Template that shows the data model using converters
<script id="tmplDates" type="text/x-jsrender">
<hr /> <span data-link="{toDateString:gameDate}"></span>
<hr /> <span data-link="{toTimeString:gameDate}"></span>
<hr /> <span data-link="{toString:gameInt}"></span>
</script>
and every seconds, I update both the date and the integer with the Observable method. The integer gets updated but not the date !
function gameLoop() {
var tDate = model.gameDate;
tDate.addHours(4);
$.observable(model).setProperty("gameDate", tDate);
var tInt = model.gameInt + 1;
$.observable(model).setProperty("gameInt", tInt);
$("#lastUpdate").text( gameDateString(model.gameDate, 0) + "-" + gameDateString(model.gameDate, 6) + " - [" + model.gameInt + "]");
window.setTimeout(gameLoop, 1000);
}
I added a line where I write the value without databinding to show that the values are updated..
Source: (StackOverflow)
Is it possible to use else tag when data linking to top level elements in JsViews?
If so where do you put the else tag in an example like this?
<tbody class="movies" data-link="{for movies tmpl='movieTmpl'}"></tbody>
<script id="movieTemplate" type="text/x-jsrender">
<tr class="hover" data-link="css-background-color{:~bgColor()}">
<td>
<span data-link="#index + 1"></span>:
<span data-link="title"></span>
</td>
<td data-link="{for languages tmpl='languageName'}"></td>
<td>
<img class="removeMovie"
src="http://www.jsviews.com/resources/images/close.png" />
</td>
</tr>
</script>
Source: (StackOverflow)
I have a select which is bound to some values from the server using jsViews. I have successfully managed to show the options but I want be able to track and set the select option to the value from my JavaScript object. This is my code:
<select id="albumChoice" data-link="selectedAlbum">
<option value="-">Please select</option>
{^{for albums}}
<option data-link="{value{:id} text{:name}} selected{:selectedAlbum}}"></option>
{{/for}}
</select>
The complete example code is in this fiddle: http://jsfiddle.net/4ZevT/
As you can see I have tried to use selected{:selectedAlbum} but that doesn't do anything. What must I do so that the option is automatically set when the page loads to the value from the server.
Source: (StackOverflow)
How can I loop a selected group/ object list only from my json data? For instance, I just want to loop "ID2" in the example below,
json,
{
"ID1": {
"items":{
"0": "VALUE1",
"1": "VALUE2",
"2": "VALUE3",
"4": "VALUE4"
}
},
"ID2": {
"items": {
"0": "VAL2-1",
"1": "VAL2-2",
"2": "VAL2-3"
}
}
}
js,
myTmpl2 = $.templates("#myTmpl2");
$("#result2").html(
myTmpl2.render(data2)
);
template,
<script id="myTmpl2" type="text/x-jsrender">
{{props #data}}
<tr>
<td>{{:key}}</td>
{{for prop}}
{{props items}}
<td>{{>key}} - {{>prop}}</td>
{{/props}}
{{/for}}
</tr>
{{/props}}
</script>
result,
ID1 0 - VALUE1 1 - VALUE2 2 - VALUE3 4 - VALUE4
ID2 0 - VAL2-1 1 - VAL2-2 2 - VAL2-3
The result I am after,
result,
ID2 0 - VAL2-1 1 - VAL2-2 2 - VAL2-3
Is it possible?
and btw, what does #data
mean in {{props #data}}
(I am using it but don't understand it!)?
can I do this if I want to select a group only - {{props #data.ID2}}
??
Source: (StackOverflow)