EzDevInfo.com

jsviews

Interactive data-driven views, MVVM and MVP, built on top of JsRender templates JsRender/JsViews

Change the scope of onAfterChange in 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)

JsRender/ JsViews: how to loop a nested json?

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)

Advertisements

jsViews - using visible in data-link attribute not working correctly

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)

How should I bind an event to DOM elements created with a JsRender custom tag?

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)

Why can't TR be a direct child of TABLE in JsViews?

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:

screen-shot-of-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)

Confusion on "Data-linked elements"

I am reading up this page http://www.jsviews.com/#linked-elem-syntax and testing a bit.

  1. 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.

  1. 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)

How to check array null or empty in jsrender?

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)

Getting the data object by using view name or place holder name

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)

How to add or edit data in an array with data-linking?

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)

Correct syntax for binding to a form in jsviews (commit 26)

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)

jsView - In contrast to #parent.data, ~root does not work in this case

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 would need help in linking a Date object in a JsViews Template

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)

Can I use an else tag while data-linking top-level elements in JsViews?

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)

jsViews - how do I set selected option from data

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)

jsrender/ jsviews: how to loop a selected object list?

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)