Two-way bindings with Kendo MVVM from remote data source - ajax

I want to bind JSON that I fetch from a remote source to elements on a page. I was hoping to use the Kendo DataSource to manage the transport and use MVVM to display and update the data.
I need help as I cannot work out how to display the remote data:
http://jsfiddle.net/digory/zxoLpej9/
Here is my JS:
$(function(){
var dataSource = new kendo.data.DataSource({
transport: {
read: {
//using jsfiddle echo service to simulate JSON endpoint
url: "/echo/json/",
dataType: "json",
type: "POST",
data: {
json: JSON.stringify({
"ItemA": "A",
"ItemB": "B"
})
}
}
},
schema: {
model: {
fields: {
ItemA: { type: "string" },
ItemB: { type: "string" }
}
}
}
});
var vm = kendo.observable({
source: dataSource,
foo: 42,
change: function(e) {
console.log("Changed!");
},
save: function() {
console.log("Saved!");
}
});
kendo.bind($("#my-container"), vm);
vm.source.read();
});
And here is the UI display code that I am trying to use to render the data:
<div id="my-container">
<div>
<label for="ItemA">Item A</span>
<input id="ItemA" data-bind="value: source.data.ItemA, events: { change: change }" />
</div>
<div>
<label for="ItemB">Item B</span>
<input id="ItemB" data-bind="value: source.data.ItemB, events: { change: change }" />
</div>
<div>
<label for="Foo">Foo</span>
<input id="Foo" data-bind="value: foo, events: { change: change }" />
</div>
<div>
<button data-bind="click: save, enabled: hasChanges" class="k-button k-primary">Save</button>
</div>
</div>

I've been playing around a bit more and think I might have found a suitable approach.
The key finding was to set the data in the view model from within the dataSource's change function:
http://jsfiddle.net/digory/yyunxgcw/
change: function() {
var view = this.view()[0];
vm.set("data", view);
},
I'm sure it can be more elegant, but it seems to be working!

Related

Simple Kendo DropDownList binding in window

I have a form with a DropDownList inside a Kendo window and I want to bind existing data to it. Examples for this abound and I've done it in other situations before, but this one (which seems like it should be really easy) is escaping me because I can't seem for the life of me to get the DropDownList to show the correct value. I figure I must be missing something really simple, but I haven't done Kendo in over a year, and looking at my previous work isn't helping me either.
Extremely simplified code:
<button onclick="OnButtonClick();">Click Me</button>
<div id="form-window"></div>
<script type="text/x-kendo-template" id="form-template">
<div class="form-group">
<label for="Url">URL</label>
<input name="Url" type="text" value="#= Url #" required="required" />
</div>
<div class="form-group">
<label for="HttpVerb">HTTP verb</label>
<input name="HttpVerb" data-bind="value:HttpVerb" data-source="httpVerbsDataSource" data-value-field="verb" data-text-field="verb" data-role="dropdownlist" />
</div>
</script>
<script type="text/javascript">
var formWindow = $("#form-window")
.kendoWindow({
title: "Form",
modal: true,
visible: false,
resizable: false,
scrollable: false,
width: 500,
actions: ["Close"],
open: function () {
kendo.init($("#form-window"));
}
}).data("kendoWindow");
var formTemplate = kendo.template($("#form-template").html());
var httpVerbsDataSource = new kendo.data.DataSource({
data: [
{ verb: "GET" },
{ verb: "POST" },
{ verb: "PUT" }
]
});
function OnButtonClick(e) {
var dataItem = {
Url: "abcdef",
HttpVerb: "POST"
};
var windowContent = formTemplate(dataItem);
formWindow.content(windowContent);
formWindow.center().open();
}
</script>
When I click the button, the window opens and the form text field is populated correctly, and the DropDownList has properly been bound to the data source, but the value in my data item is not selected.
JS Bin: https://jsbin.com/wariyorilo/edit?html,js,output
What am I missing? Thanks in advance.

Pass multiple Id's against multiple values in database

I'm working on a task that uses autocomplete textbox items containing names, stores in textbox or in listbox with their associated Id's(hidden) and inserted into the required table (only their related id's). I'm working on mvc 5 application. So far I've achieved to add value in listbox with names but not Id's. And trying to add the listbox values get stored in database. Below is my code.
Note:- I'm using partial view to display listbox when the button clicks. The current scenario is that it the listbox overwrites the first value when inserting second value.
StudentBatch.cs
public List<string> selectedids { get; set; }
public List<string> SelectedNames { get; set; }
Create.cshtml
<div class="form-group">
<div class="col-md-12">
#Html.EditorFor(model => model.StudentName, new { id = "StudentName" })
<input type="button" value="Add Text" id="addtypevalue" />
<div id="typevaluelist"></div>
</div>
</div>
<div id="new" style="display:none;">
<div class="typevalue">
<input type="text" name="typevalue" />
<button type="button" class="delete">Delete</button>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Add Students" class="btn btn-default" />
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
$("#StudentName").autocomplete({
//autocomplete: {
// delay: 0,
// minLength: 1,
source: function (request, response)
{
$.ajax({
url: "/Student/CreateStudent",
type: "POST",
dataType: "json",
data: { Prefix: request.term },
success: function(data) {
try {
response($.map(data,
function (item)
{
return { label: item.FirstName, value: item.FirstName };
}));
} catch (err) {
}
}
});
},
messages:
{
noResults: "jhh", results: "jhjh"
}
});
});
</script>
<script>
$('#addtypevalue').click(function () {
$(document).ready(function () {
var selValue = $('#StudentName').val();
$.ajax({
type: "GET",
url: '#Url.Action("GetListBox", "Student")',
dataType: "html",
data: { CourseId: selValue },
success: function (data) {
$("#partialDiv").html(data);
},
failure: function (data) {
alert('oops something went wrong');
}
});
});
});
</script>
GetListBox.cshtml
#model WebApplication1.Models.StudentBatch
#if (ViewBag.Value != null)
{
#Html.ListBoxFor(m => m.SelectedNames, new SelectList(Model.SelectedNames))
}
StudentController.cs
public PartialViewResult GetListBox(string CourseID)
{
Context.Student studCont = new Context.Student();
Models.StudentBatch student = new Models.StudentBatch();
student.SelectedNames = new List<string>();
student.SelectedNames.Add(CourseID);
ViewBag.Value = student;
return PartialView(student);
}

DropDownList not populating with Data from Datasource

Hi I'm doing my first app mobile using telerik appBuilder and I can't get the Kendo datasource to work with a dropdown list.
The result of my webservices is below but I can't get the correct data-bind for that result.
{"d":[{"id":2209,"nom":"Test 1"},{"id":23608,"nom":"Test 2"},{"id":24061,"nom":"Test 3"},{"id":24741,"nom":"Test 4"},{"id":27347,"nom":"Test 5"}]}
Pls, any ideas? Thanks a lot.
/* product.html*/
<div id="product" data-role = "view"
data-layout = "sharedlayout" data-model="app.productService.viewModel">
<div class="view-content">
<form >
<div data-role="listview" data-style="inset">
<div>
Products:
<select id="product" data-role="dropdownlist"
data-bind="source: productsdataSource "
data-text-field="id"
data-value-field="product">
<option value="0"> </option>
</select>
</div>
</div>
</form>
</div>
</div>
ProductViewModel.js
(function (global)
{
var ProductsViewModel,
app = global.app = global.app || {};
ProductsViewModel = kendo.data.ObservableObject.extend (
{
getProducts: function() {
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "urlexample",
type:"post",
contentType: "application/json; charset=utf-8",
dataType: "json"
}
},
schema: {
data: "d"
},
type: 'json'
});
}
});
app.productService = { viewModel: new ProductsViewModel() };
})(window);
I'm not sure exactly where your problem lies, but i've got a few ideas...
Why are you extending the observable? Why not just use kendo.observable({})?
Your viewModel is returning a function, not an object which is what Kendo UI would be expecting.
I think you might be over-complicating this slightly. I've put together a dead simple example...
http://plnkr.co/edit/T41nZqZNLqtOTfjG8upK?p=preview
Might I also suggest that you drop the data-role="dropdownlist"? Mobile devices have their own select list implementations and this way you can use the native select ability on the device.

data-bind not working in List View template within Grid detail template

I need help using a Kendo UI list view which lives within a grid row detail template.
here is something I have done so far.
<div id="grid">
</div>
<script type="text/x-kendo-template" id="gridDetailTemplate">
<div class='grid-edit'>
<div class='edit-list'></div>
</div>
</script>
<script type="text/x-kendo-template" id="editItemtemplate">
<div class='edit-Item'>
#if(Type=='string'){#
<ul><li><b>#:Name#</b></li><li><input class='inputString' value='#:DataVal()#'/></li></ul>
#}else if(Type=='number'){#
<ul><li><b>#:Name#</b></li><li><input class='inputNumber' data-role='numerictextbox' data-type='number' value='#:DataVal()#'/></li></ul>
#}else if(Type=='date'){#
<ul><li><b>#:Name#</b></li><li><input class='inputDate' data-role='datepicker' value='#:kendo.toString(DataVal(),'MM/dd/yyyy')#'/></li></ul>
#}else if(Type=='boolean'){Name #<input type='checkbox'/>
#}#
</div>
</script>
<script type="text/javascript">
$(document).ready(function () {
$.get("http://localhost:4916/DataAttribute", function (data, status) {
var selFields = new Object();
$.each(data, function (index, elem) {
selFields[elem.Name] = new Object();
selFields[elem.Name]["type"] = elem.Type;
});
$("#grid").kendoGrid({
dataSource: {
type: "json",
transport: {
read: { url: "http://localhost:4916/Deal",
dataType: "json"
}
},
schema: {
data: "Data", total: "Total",
model: {
fields: selFields
}
}
},
height: 430,
filterable: true,
sortable: true,
pageable: false,
detailTemplate: kendo.template($("#gridDetailTemplate").html()),
detailInit: detailInit,
columns: [{
field: "SecurityName",
title: "Security Name",
width: 250
},
{
field: "DateOfAcquisition",
title: "Date Of Acquisition",
width: 120,
format: "{0:MM/dd/yyyy}"
}, {
field: "Acres",
title: "Acres",
width: 120
}
]
});
});
});
function detailInit(e) {
$.get("http://localhost:4916/DataAttribute", function (data, status) {
var detailRow = e.detailRow;
detailRow.find(".edit-list").kendoListView({
dataSource: {
data: data,
schema: {
model: {
DataVal: function () {
switch (this.get("Type")) {
case "number"
}
if (e.data[this.get("Name")])
return e.data[this.get("Name")];
else
return '';
}
}
}
},
template: kendo.template($("#editItemtemplate").html())
});
});
}
</script>
My code gets dynamic field list and binds it to the data source for grid.
Then, in the detailInit event, I find the div within row detail and convert it into kendo UI list, for which the template have been created.
Now, when I use data-bind="value: DataVal()" ,it doesn't pick up the values of List data source. It works the way I have done i.e. value="#: DataVal() #". But, data-role does not convert the fields to specified types which are datepicker and numericinput in my case.
I believe that data-role not being used is caused due to same issue as data-bind not being read.
Can anyone help me out with this? Also, feel free to suggest any alternate ways and general code improvements. I am an ASP.NET developer and usually don't work on pure html and javascript.
PS: I would be happy to provide the context on what I am trying to achieve here if anyone is interested.
Thanks in advance.
If you can rig up a jsFiddle or jsBin example that would help debug the issue.
However, try removing the parenthesis:
data-bind="value: DataVal"
Kendo should detect that DataVal is a function and call it on its own.
I experienced a similar situation in a listview template. I created a JSFiddle to demonstrate:
http://jsfiddle.net/zacharydl/7L3SL/
Oddly, the solution is to wrap the contents of the template in a div. It looks like your template already has this, so YMMV.
<div id="example">
<div data-role="listview" data-template="template" data-bind="source: array"></div>
</div>
<script type="text/x-kendo-template" id="template">
<!--<div>-->
<div>method 1: #:field#</div>
<div>method 2: <span data-bind="text: field"></span></div>
<input data-role="datepicker" />
<!--</div>-->
</script>
var model = kendo.observable({
array: [
{ field: 'A'},
{ field: 'B'}
]
});
kendo.bind($('#example'), model);

Kendo UI: Update transport doesn't trigger after calling datasource sync

Im struggling on this in hours now, I cant find a good documentation on how to implement simple ajax UPDATE on server using forms and Kendo MVVVM and datasource.
KENDO MVVM
$(function() {
var apiUrl = "http://a31262cd2f034ab8bcda22968021f3b8.cloudapp.net/api",
meetingDatasource = new kendo.data.DataSource({
transport: {
read: {
url: apiUrl + "/meetings/4",
dataType: "jsonp"
},
update: {
type: "PUT",
url: apiUrl + "/meetings",
contentType: "application/json; charset=utf-8",
dataType: 'json',
},
parameterMap: function(options, operation) {
return kendo.stringify(options);
}
},
batch: true,
change: function() {
},
schema: {
model: {
id: "Id",
fields: {
Title: { editable: true },
StartTime: { type: "date" },
EndTime: { type: "date" }
}
}
}
});
meetingDatasource.fetch(function () {
var viewModel = kendo.observable({
description: result.Description,
title: result.Title,
venue: result.Location,
startDate: result.StartTime,
endDate: result.EndTime,
saveChanges: function (e) {
//im not sure with this line
this.set("Title", this.Title);
meetingDatasource.sync();
e.preventDefault();
}
});
kendo.bind($("#view"), viewModel);
});
});
THE UI
<ul class="forms" id="ul-meeting">
<li>
<label for="title" >Title:</label>
<input data-bind="value: title" class="k-textbox" style="width:350px;"/>
</li>
<li>
<label for="description" >Description:</label>
<textarea data-bind="value: description" id="description" rows="6" cols="80" class="k-textbox" style="width:350px;"></textarea>
</li>
<li>
<label for="location">Venue:</label>
<textarea data-bind="value: venue" id="location" rows="4" cols="80" class="k-textbox" style="width:350px;"></textarea>
</li>
<li>
<p>
<label for="start-datetime">Start:</label>
<input data-bind="value: startDate" id="start-datetime" style="width:200px;" />
</p>
<p>
<label for="end-datetime">Finish:</label>
<input data-bind="value: endDate" id="end-datetime" style="width:200px;" />
</p>
</li>
</ul>
The problem is, the TRANSPORT READ triggers but the TRANSPORT UPDATE never triggers even if I explicity call the Datasource.sync(). Is is something I am missing here?
Your code is not complete (you are not showing what is result or how you trigger saveChanges but from what I see the problem is that you are not updating the content of the DataSource (meetingDataSource).
In your code that you copy the fields from result into and ObservableObject but you never update the content of the DataSource. When you do this.set, in that context this is not the DataSource so when you call sync you are doing nothing.
Try doing:
meetingDatasource.data()[0].set(`Title`, this.Title);
meetingDatasource.sync();
This should do the trick!

Resources