Is it possible for jsrender to render a field name dynamically? - javascript

Is it possible to have a dynamic field name in jsrender like this.
{{<cellcontent>}}
Common template as generic one. Cell content value is bound to a datasource. Is it possible?

Your question is not very clear, but if you are asking about using JsRender templates along with data-binding so that when the data changes the rendered result is automatically updated, dynamically, well yes, that is what JsViews is all about: http://www.jsviews.com/#jsviews. (JsViews is a data-binding layer on top of JsRender).
Here is a simple example:
var tmpl = $.templates("#myTemplate"),
data = {name: "Jo"};
tmpl.link("#content", data);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//www.jsviews.com/download/jsviews.js"></script>
<script id="myTemplate" type="text/x-jsrender">
{^{:name}} <br/>
<input data-link="name trigger=true" />
</script>
<div id="content"></div>

Related

How to create dynamic div and add data into it from different elements in other xhtml?

In below code I want to add the div dynamically under div tag with id="includedContent". And also load data using number of ids.So instead of having a hardcoded Id(123) to load method i want to make it accept Array of ids and displqay the data in the dynamically created tag???
<script src="js/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
function vikas(){
var i=0;
$(function(){
$("#includedContent").load("b.xhtml #123");
});
}
</script>
</head>
<body>
<button type="button" style="width:80px; height:40px;" onclick="vikas()">Click</button>
<div id="includedContent" >vikas<img click="vikas()" src="www.google.com" alt=""></img><br/></div>
</body>
This looks like a perfect case for using a templating engine like MustacheJS http://mustache.github.io/
It allows you to create a template into a variable and then "throw" a JSON-Object onto a new instance of an mustacheJS and it will replace some placeholders you are defining in the template (they'll look like this:{{variable}}). You can find easy follow examples on their website.
I hope i could help.

How do I add Angular functionality to newly-added HTML?

I have an HTML page with Angular. I want to click a button that adds an Angular input tag to the DOM. But when I do so, the new input text field does not seem to work the way I would expect it.
My HTML looks like this:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0-rc.2/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
var app= angular.module("myApp",[]);
app.controller("myCtrl",function($scope){
});
$(function(){
$("#button").click(function(){
$("body").append("<input type=\"text\" ng-model=\"bar\"><br>{{bar}}");
});
});
</script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<button id="button">click me</button>
<input type="text" name="something" ng-model="foo"><br>
{{foo}}
</body>
</html>
I can use Angular's functions just fine when with the input tag already there. When I type something in the text field, the output appears. But when I click the button and the new input text field comes up, typing in it does nothing.
What am I missing?
How do I fix this?
You can't mix JQUERY and Angular in the way you are doing it. You have to choose one framework and stick to its principles.
In order to add a control the "View" in angular you could use "Directives". Another options is to have an object in your Model and the chances to this object will interact with your controller and this will inform the View to add another control.
Angular is an MVC framework therefore you should not manipulate the View(html) through another framework. Angular was meant to fix and simplify this manipulations with a proper separation or layers.
You can refer to this other post on how to perform this:
How to dynamically add input rows to view and maintain value in angularjs ng-model as array item
To do it in AngularJS:
<body ng-app="myApp" ng-controller="myCtrl">
<button id="button" ng-click="showBarInput=true">click me</button>
<div ng-show="showBarInput">
<input type="text" ng-model="bar"><br>
{{bar}}
</div>
<input type="text" name="something" ng-model="foo"><br>
{{foo}}
</body>
The AngularJS framework is a Model-View-Whatever framework. The model drives the view. In this case, $scope.showBarInput controls the visibility of the elements.

Angular js in Dynamically create controls

In my application one block is loaded with the controls dynamically. After loading the dynamic controls the data is update by using the angular js. But the angular js is working with static placed controls. But not with dynamic controls.
Here I placing the dynamic code What I tried to get.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
$("#ren").html('<p>Name: <input type="text" ng-model="name"></p>');
});
});
</script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="">
<p>Input something in the input box:</p>
<div id="ren"></div>
<p ng-bind="name"></p>
</div>
<button>click</button>
</body>
</html>
Here the input control dynamically added to the div. The text I enter in control does not appering on paragraph. But this work fine if the input control place in div static.
Am I doing any wrongly. please solve my problem.
Probably your html attached via jquery function, is not registered to angular's watch tree. as a result, it doesn't trigger a digest cycle when you type to input with ng-model. Also this kind of usages angular with jquery in the dom edition level is not recommended. In my opinion, you should use directive instead of that jquery-dom operation
I'd prefer to do it in angular way, rather than mixing jQuery with angular. Because directly adding DOM to angular context will not worked as angular compiled DOM(means angular binding will not work on newly injected DOM). You need to compile that DOM with $compile service with specific scope before injecting it into DOM to enable binding on it.
Lets follow this way, which is fully angular way of doing it. There would be ng-click directive on the button, and will toggle a flag to show and hide element & we will render that array using ng-if
HTML
<p>Input something in the input box:</p>
<div id="ren">
<p ng-if="showName">Name: <input type="text" ng-model="name"></p>
</div>
<p ng-bind="name"></p>
</div>
<button type="button" ng-click="showName!=showName">click</button>

JsViews how to make data binding happen on root object as well as its nested properties?

I am experiencing odd behavior when data linking an object to a form that led me to re-question what exactly is being data bound?
Basically I have a form that creates new Companies as well as updates them. The actual creation/update is done via ajax, which is why I am using the same form for both purposes. In the case when I have to create a company, everything works as I expect. However when I have to update a company, things don't work like how I expect them to. Please have a look at the following code.
Here is my sample Form HTML:
<div id="result"></div>
<script type="text/x-jsrender" id="CompanyFormTemplate">
<form>
<input type="text" data-link="Company.Name" />
</form>
</script>
Here is my Javascript code:
var app = new CompanyFormContext();
function CompanyFormContext() {
this.Company = {
Name: ''
};
this.setCompany = function (company) {
if (company) {
$.observable(this).setProperty('Company', company);
}
};
};
$(function () {
initPage();
...
if (...) {
// we need to update company information
app.setCompany({ Name: 'Company ABC' });
}
});
function initPage() {
var template = $.templates('#CompanyFormTemplate');
template.link("#result", app);
}
Instead of the form input showing 'Company ABC', it is empty. However if I enter anything in it, then the Company.Name value does change! But while I want the input to data bind to Name property of my Company object, I also want it to be aware of any changes made to the (parent) Company object and update it's data binding to it's Name property accordingly.
So my question is how should I change the way I am writing this code so that I can achieve a data bound both on the root object as well as the property?
The issue you were having was because in your scenario, you have paths like Company.Name for which you want to data-link to changes not only of the leaf property but also to changes involving replacing objects higher up in the path (in this case the Company).
For that you need to use the syntax data-link="Company^Path".
See the section Paths: leaf changes or deep changes in this documentation topic:
http://www.jsviews.com/#observe#deep.
See also the examples such as Example: JsViews with plain objects and array in this topic: http://www.jsviews.com/#explore/objectsorvm.
Here is an update of your jsfiddle, using that syntax: https://jsfiddle.net/msd5oov9/2/.
BTW, FWIW, in your fix using {^{for}} you didn't have to use a second template - you could alternatively have written:
<form class="form-horizontal">
{^{for Company}}
...
<input type="text" data-link="Name" />
{{/for}}
</form>
To respond also to your follow-up question in your comment below, you can associate any 'block' tag with a template. Using tmpl=... on the tag means you have decided to separate what would have been the block content into a separate re-usable template. (A 'partial', if you will). The data context for that template will be the same as it would have been within the block.
So specifically, {{include}} {{if}} and {{else}} tags do not move the data context, but {{for}} and {{props}} do. With custom tags you can decide...
So in your case you could use either {^{for Company tmpl=.../}} or {{include tmpl=.../}} but in the second case your other template that you reference would use <input type="text" data-link="Company^Name" /> rather than <input type="text" data-link="Name" />.
Here are some relevant links:
http://www.jsviews.com/#samples/jsr/composition/tmpl
http://www.jsviews.com/#includetag
http://www.jsviews.com/#fortag
I discovered one way to achieve this. It might seem complex at first but it will make sense once you understand it properly.
(PS: I wish there was a sample like this. I might just blog about it.)
HTML Markup:
<script type="text/x-jsrender" id="CompanyFormTemplate">
<form>
{^{for Company tmpl="#CompanyDetailsTemplate" /}
</form>
</script>
<script type="text/x-jsrender" id="CompanyDetailsTemplate">
<input type="text" data-link="Name" />
</script>
Javascript: No changes needed from code above.
Okay so as I said, the solution might look complicated but it turns out all I really had to do was to set up data binding first on the Company object, and then to it's property objects. I wonder if there is a more elegant solution (i.e. one in which all of this can be achieved in a single template) however this solution ensures that data-binding is happening both on the parent object as well as its' properties.
I have posted a JsFiddle for this solution, so if anyone comes across this problem and wants to understand how this solution would work for their particular problem, they will be able to play with a working solution.

Binding an event after a page reload and creating new html element using Knockout.js, HTML and JS only?

I am new to knockout libraries and we are working on an iPad web app. The situation is when a user check a checkbox in a HTML page, we need to add a new div in the page with some text boxes in it and remove it when he uncheck those.
Point to be noted: the new div is binded to data that needs to be default loaded in the text box or selects.
Its an iPad web app. It uses Knockout, jQuery, JS and HTML with MVVM.
The question is, can Knockout bind html elements after the page load, as custom handler works/register themselves only during init and can a dynamic div be created using js and html, if yes then how to put it between two static divs?
You can bind elements after page load using ko.applyBindings(viewModel, ElementSelector), like so:
ko.applyBindings(myModel, $("#myDiv"));
However, this isn't something you generally want to do. It's much easier to use the If binding in Knockout, which will dynamically add or remove child elements from the page.
<input type="checkbox" data-bind='checked: showChild' />
<div id="container" data-bind="if: showChild">
<!-- stuff here will only be generated if the checkbox is selected -->
</div>
If you had multiple different elements to show based on a value of something, say a select list, you could use the template feature instead:
//viewmodel properties
self.Options = ko.observableArray(["Name", "Age", "Height"])
self.TemplateToUse = ko.observable()
//html
<select data-bind="options: Options, value: TemplateToUse">
</select>
<div data-bind='template: { name: TemplateToUse }'>
<!-- template whose name is selected value -->
</div>
//templates
<script type="text/html" id="Age">
<span>Age</span>
</script>
<script type="text/html" id="Name">
<span>Name</span>
</script>
<script type="text/html" id="Height">
<span>Height</span>
</script>

Categories