How to bind data from model to view using knockoutJS - asp.net-mvc

in my application i'm able to get data-collection from model when i'm binding it using knockoutJS that it generate an error on console, i need with data-bind attribute data-class, i'm doing so but not working;
my view binding code as :
<div class="filter-map-content" data-bind="foreach: { data: Services, as: 'service' }">
<input type="checkbox" class="custom-checkbox" data-bind="css: { 'id': service.id, 'data-class': 'GTM_MMCheckbox_' + service.title + '_' + service.id }" data-class=" 'GTM_MMCheckbox_' + service.title + '_' + service.id" />
</div>
i'm able to get data collection when i write it on console , i'm getting data collection as result
data-class is not finding in my javascript code
but data-collection is available

<div class="filter-map-content" data-bind="foreach: { data: Services, as: 'service' }">
<input type="checkbox" class="custom-checkbox" data-bind="attr: { 'id': service.id, 'data-class': 'GTM_MMCheckbox_' + service.title + '_' + service.id }" />
</div>
you have to use the "attr"-binding ;)
...and if your "service.title" or "service.id" is observable you have to write e.g. service.title()

Related

Render view fragments directly, using thymeleaf

I am trying to get just a part of the view(fragment) from a template, i just end up getting the following error
org.thymeleaf.exceptions.TemplateInputException: Error resolving template "path/to/template::fragment", template might not exist or might not be accessible by any of the configured Template Resolvers
And this is the current configuration:
TemplateResolver resolver = new ServletContextTemplateResolver();
resolver.setTemplateMode("HTML5");
resolver.setPrefix("/WEB-INF/templates/");
resolver.setCharacterEncoding("UTF-8");
resolver.setSuffix(".html");
resolver.setCacheable(false);
engine = new TemplateEngine();
engine.setTemplateResolver(resolver);
It soud be possible as it is given as a feature(but using spring-mvc, which I am not):
http://www.thymeleaf.org/whatsnew21.html#spfrag
The site application works using jsp, and the code that is failing looks like this:
render("surveys/survey", params,request,response);//This works
render("surveys/survey::surveyBody", params,request,response);//This fails
public static String render(String template,Map<String,?> context,HttpServletRequest request, HttpServletResponse response){
IContext iContext = new WebContext(request,response,request.getServletContext(),Locale.US, context);
return engine.process(template, iContext);
}
inside the template there is something like this
<div th:fragment="surveyBody">
<div th:each="field,idx : ${survey.fields}" th:id="${'field_' + field.id}" th:class="${field.type + ' row outter'}">
<input type='hidden' th:id="${'field_' + field.id + '_id'}" id='field_100_id' value='100' />
<input type='hidden' th:id="${'field_' + field.id + '_type'}" id='field_100_type' th:value='${field.type}' />
<input type='hidden' th:id="${'field_' + field.id + '_order'}" id='field_100_order' th:value='${field.obj.order}' />
<input type='hidden' th:id="${'field_' + field.id + '_outstanding'}" id='field_100_outstanding' value='-1' />
<h3 th:utext="${field.obj.title[0].title}">title</h3>
<h4 th:if="${!field.obj.subTitle.isEmpty()}" th:utext="${field.obj.subTitle[0].title}">subtitle</h4>
<div class="answers row">
<div th:replace="surveys/questions::${field.type}(${field},${disabled},${idx.index})"></div>
</div>
</div>
</div>
th:fragment is called in template using th:replace or th:include attributes.
Try to create a clear file (surveys/surveyfragment) and write there:
<div th:replace="surveys/survey::surveyBody"/>
And then call it:
render("surveys/surveyfragment", params,request,response);
Should work

Generate code for knockout binding for ASP.Net MVC

I have worked with knockout a little bit. It is a good client side data binding js library. A template is bound and populated on the client side as follows:
<h3>Are you sure you want to delete this?</h3>
<fieldset>
<legend>Delete</legend>
<div class="display-label">
Student Id
</div>
<div class="display-field">
<input data-bind="value: StudentId" />
</div>
<div class="display-label">
First Name
</div>
<div class="display-field">
<input data-bind="value: FirstName" />
</div>
<div class="display-label">
Last Name
</div>
<div class="display-field">
<input data-bind="value: LastName" />
</div>
<div class="display-label">
Age
</div>
<div class="display-field">
<input data-bind="value: Age" />
</div>
</fieldset>
the above way we write html to bind data
this way populate template by js code
$(function () {
ko.applyBindings(StudentListVM);
StudentListVM.getStudents();
});
//View Model
var StudentListVM = {
Students: ko.observableArray([]),
getStudents: function () {
var self = this;
$.ajax({
type: "GET",
url: '/Student/FetchStudents',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
self.Students(data); //Put the response in ObservableArray
},
error: function (err) {
alert(err.status + " : " + err.statusText);
}
});
},
};
self.editStudent = function (student) {
window.location.href = '/Student/Edit/' + student.StudentId;
};
self.deleteStudent = function (student) {
window.location.href = '/Student/Delete/' + student.StudentId;
};
//Model
function Students(data) {
this.StudentId = ko.observable(data.StudentId);
this.FirstName = ko.observable(data.FirstName);
this.LastName = ko.observable(data.LastName);
}
The above code works and generates the UI on the client side.
I would like to know if there is any scaffolding option in MVC which generates the above html with binding expression and also generates the required js view model.
If this does not exist then I would appreciate suggestions on how to achieve it.
Take a look on Knockout mvc
You can write appropriate #helper method
Don't forget about T4
you can write your own extension for HtmlHelper

jQuery Mobile and Knockout.js templating, styling isnt applied

Ok so this is beginning to drive me insane. I have for several hours now searched and searched, and every single solution doesnt work for me. So yes, this question might be redundant, but i cant for the life of me get solutions to work.
I have a bunch of checkboxes being generated by a jquery template that is databound via knockout.js. However, it turns up unstyled. Afaik, it is something about jquery mobile does the styling before knockout renderes the template, so it ends up unstyled.
I have tried numerous methods to no avail, so i hope someone here can see what i am doing wrong.
(i am using jquery mobile 1.2.0 , jquery 1.8.2 and knockout 2.2.1)
This is the scripts:
<script type="text/javascript">
jQuery.support.cors = true;
var dataFromServer = "";
// create ViewModel with Geography, name, email, frequency and jobtype
var ViewModel = {
email: ko.observable(""),
geographyList: ["Hovedstaden","Sjælland","Fyn + øer","Nordjylland","Midtjylland","Sønderjylland" ],
selectedGeographies: ko.observableArray(dataFromServer.split(",")),
frequencySelection: ko.observable("frequency"),
jobTypes: ["Kontor (administration, sekretær og reception)","Jura","HR, Ledelse, strategi og udvikling","Marketing, kommunikation og PR","Handel og service (butik, service, værtinde og piccoline)","IT","Grafik og design","Lager, chauffør, bud mv.","Økonomi, regnskab og finans","Kundeservice, telefoninterview, salg og telemarketing","Sprog","Øvrige jobtyper"],
selectedJobTypes: ko.observableArray(dataFromServer.split(",")),
workTimes: ["Fulltid","Deltid"],
selectedWorkTimes: ko.observableArray(dataFromServer.split(","))
};
// function for returning checkbox selection as comma separated list
ViewModel.selectedJobTypesDelimited = ko.dependentObservable(function () {
return this.selectedJobTypes().join(",");
}, ViewModel);
var API_URL = "/webapi/api/Subscriptions/";
// function used for parsing json message before sent
function omitKeys(obj, keys) {
var dup = {};
var key;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
if (keys.indexOf(key) === -1) {
dup[key] = obj[key];
}
}
}
return dup;
}
//Function called for inserting new subscription record
function subscribe() {
if($("#jobmailForm").valid()=== true){
//window.alert("add subscriptiooncalled");
var mySubscription = ko.toJS(ViewModel);
//var json = JSON.stringify(mySubscription);
var jsonSmall = JSON.stringify(omitKeys(mySubscription, ['geographyList','jobTypes','selectedJobTypesDelimited','workTimes']));
//window.alert(jsonSmall);
$.ajax({
url: API_URL,
cache: false,
type: 'POST',
contentType: 'application/json',
data: jsonSmall,
success: function (data) {
window.alert("success");
},
error: function (error) {
window.alert("ERROR STATUS: " + error.status + " STATUS TEXT: " + error.statusText);
}
});
}
}
function initializeViewModel() {
// Get the post from the API
var self = this; //Declare observable which will be bind with UI
// Activates knockout.js
ko.applyBindings(ViewModel);
}
// Handle the DOM Ready (Finished Rendering the DOM)
$("#jobmail").live("pageinit", function() {
initializeViewModel();
$('#jobmailDiv').trigger('updatelayout');
});
</script>
<script id="geographyTmpl" type="text/html">
<input type="checkbox" data-role="none" data-bind="attr: { value: $data }, attr: { id: $data }, checked: $root.selectedGeographies" />
<label data-bind="attr: { for: $data }"><span data-bind="text: $data"></span></label>
</script>
<script id="jobTypeTmpl" type="text/html">
<label><input type="checkbox" data-role="none" data-bind="attr: { value: $data }, checked: $root.selectedJobTypes" /><span data-bind="text: $data"></span></label>
</script>
Note, "jobmail" is the surrounding "page" div element, not shown here. And this is the markup:
<div data-role="content">
<umbraco:Item field="bodyText" runat="server"></umbraco:Item>
<form id="jobmailForm" runat="server" data-ajax="false">
<div id="jobmailDiv">
<p>
<label for="email">Email</label>
<input type="text" name="email" id="email" class="required email" data-bind="'value': email" />
</p>
<fieldset data-role="controlgroup" data-mini="true" data-bind="template: { name: 'geographyTmpl', foreach: geographyList, templateOptions: { selections: selectedGeographies } }">
<input type="checkbox" id="lol" />
<label for="lol">fkfkufk</label>
</fieldset>
<fieldset data-role="controlgroup" data-mini="true">
<p data-bind="template: { name: 'jobTypeTmpl', foreach: jobTypes, templateOptions: { selections: selectedJobTypes } }"></p>
</fieldset>
<fieldset data-role="controlgroup" data-mini="true">
<input type="radio" id="frequency5" name="frequency" value="5" data-bind="checked: frequencySelection" /><label for="frequency5">Højst 5 gange om ugen</label>
<input type="radio" id="frequency3" name="frequency" value="3" data-bind="checked: frequencySelection" /><label for="frequency3">Højst 3 gange om ugen</label>
<input type="radio" id="frequency1" name="frequency" value="1" data-bind="checked: frequencySelection" /><label for="frequency1">Højst 1 gang om ugen</label>
</fieldset>
<p>
<input type="button" value="Tilmeld" class="nice small radius action button" onClick="subscribe();">
</p>
Tilbage
</div>
</form>
Alternate method of invoking the restyling (doesnt work either):
$(document).on('pagebeforeshow', '#jobmail', function(){
// Get the post from the API
var self = this; //Declare observable which will be bind with UI
// Activates knockout.js
ko.applyBindings(ViewModel);
});
// Handle the DOM Ready (Finished Rendering the DOM)
$("#jobmail").live("pageinit", function() {
$('#jobmail').trigger('pagecreate');
});
Use a custom binding (Knockout) to trigger jQuery Mobile to enhance the dynamically created content produced by Knockout.
Here is a simple custom binding:
ko.bindingHandlers.jqmEnhance = {
update: function (element, valueAccessor) {
// Get jQuery Mobile to enhance elements within this element
$(element).trigger("create");
}
};
Use the custom binding in your HTML like this, where myValue is the part of your view model that changes, triggering the dynamic content to be inserted into the DOM:
<div data-bind="jqmEnhance: myValue">
<span data-bind="text: someProperty"></span>
My Button
<input type="radio" id="my-id" name="my-name" value="1" data-bind="checked: someOtherProperty" /><label for="my-id">My Label</label>
</div>
In my own case, myValue was part of an expression in an if binding, which would trigger content to be added to the DOM.
<!-- ko if: myValue -->
<span data-bind="jqmEnhance: myValue">
<!-- My content with data-bind attributes -->
</span>
<!-- /ko -->
Every dynamically generated jQuery Mobile content must be manually enhanced.
It can be done in few ways, but most common one can be done through the jQuery Mobile function .trigger( .
Example:
Enhance only page content
$('#page-id').trigger('create');
Enhance full page (header + content + footer):
$('#page-id').trigger('pagecreate');
If you want to find more about this topic take a look my other ARTICLE, to be more transparent it is my personal blog. Or find it HERE.

knockout+jqm weird checkbox issue

I have a block of code which is supposed to loop over an observable array, and generate a series of grouped checkboxes (as in this example ).
Here's what I'm getting instead. http://dl.dropbox.com/u/495070/shared/2012-03-28_09.03.33.000.png
here's a jsFiddle that demonstrates the issue.
And here's the (not as useful as the fiddle) code snippet that generates it.
<fieldset id="myList" data-role="controlgroup" data-bind='foreach : acRoleOps()'>
<legend>
</legend>
<br><br><br><h4><span data-bind="text: $root.opNameGet(OperationID)"></span></h4>
<input data-theme="c" type="checkbox" data-role="controlgroup" data-bind="attr: { 'data-id': 'checkbox-bcreate-' + ID, name: 'checkbox-bcreate-' + ID, id: 'checkbox-bcreate-' + ID }, checked: BCreate, click: $parent.opPrivsToggle" />
<label data-theme="c" data-bind="attr: { for: 'checkbox-bcreate-' + ID }">Create</label>
<input data-theme="c" type="checkbox" data-role="controlgroup" data-bind="attr: { 'data-id': 'checkbox-bread-' + ID, name: 'checkbox-bread-' + ID, id: 'checkbox-bread-' + ID }, checked: BRead, click: $parent.opPrivsToggle" />
<label data-theme="c" data-bind="attr: { for: 'checkbox-bread-' + ID }">Read</label>
<input data-theme="c" type="checkbox" data-role="controlgroup" data-bind="attr: { 'data-id': 'checkbox-bedit-' + ID, name: 'checkbox-bedit-' + ID, id: 'checkbox-bedit-' + ID }, checked: BEdit, click: $parent.opPrivsToggle" />
<label data-theme="c" data-bind="attr: { for: 'checkbox-bedit-' + ID }">Edit</label>
<input data-theme="c" type="checkbox" data-role="controlgroup" data-bind="attr: { 'data-id': 'checkbox-bdelete-' + ID, name: 'checkbox-bdelete-' + ID, id: 'checkbox-bdelete-' + ID }, checked: BDelete, click: $parent.opPrivsToggle" />
<label data-theme="c" data-bind="attr: { for: 'checkbox-bdelete-' + ID }">Delete</label>
</fieldset>
Has anyone seen this before? If so, can you point out where I went wrong?
Thanks!
You need to use the knockout <!-- ko foreach: myItems -->
http://knockoutjs.com/documentation/foreach-binding.html
http://jsfiddle.net/vNcNC/38/
document.ready() doesn't work on jQuery mobile because pages are dynamically loaded. Instead, use the pageInit event. See here: http://jsfiddle.net/vNcNC/17/ Now you've still got some issues with Knockout, but I'm not too familiar with it so I can't help with those.
I think this is a conflict between the time KO is generating your markup and the time jquery mobile is applying its custom skinning. I found one issue with your code. I think the foreach is on the wrong element. I wrapped your fieldset in a new div and applied the foreach to that.
<div data-bind='foreach : acRoleOps()'>
<fieldset id="opsList" data-role="controlgroup">
I'm not too familiar with jquery mobile but here's how I proved that this is the case. I removed the references and just checked that KO generated the correct markup. With the above change it appears to do so.
http://jsfiddle.net/madcapnmckay/THG9F/
Here is the jquery mobile only version with the generated markup pasted in.
http://jsfiddle.net/madcapnmckay/tuWgM/1/
As you can see KO is generating the correct markup, there is just a timing conflict.
Hope this helps.

How to write the following in MVC?

How can I write the following in MVC?
<input type="text" name="ProjectList[' + count++ + '].ID" value = ' + value + ' />
Use code expressions in <%= ... %> block in the attributes.
<input type="text" name="<%= ProjectList[count++].ID %>" value = ' + value + ' />
If the value is meant to be another property of the ProjectList item... then setting a local variable would be easier:
<% var item = ProjectList[count++].ID; %>
<input type="text" name="<%= item.ID %>" value = '<%= item.value %>' />
Albeit that the HTML helpers (see other answer) provides a better approach.
NB. In .NET 4 prefer <%: ... %> to ensure things are HTML Encoded.
<%= Html.TextBox("ProjectList[" + (count++) + "].ID",
value, new { #class = "css" }) %>

Resources