How to reuse kendo ui remote binding datasource (change transport.read.data then refresh) - javascript

I want to ask if it's possible to reuse an remote binding kendo.data.Datasource instead of create new one with new parameters.
My scenario is that I have a search box and a list view. When user entering in search box, a request is sent to server with parameter of the search box value. I was able to make it works fine by create new kendo.data.Datasource each keyup event but memory became a concern to me.
var viewModel = kendo.observable({
searchId: "", // searchbox value
searchResult: null, // search result listview datasource
searchFnc: function() { // search function
// QUESTION: is there any way to update the current datasource object
// to refresh the list view instead of create new object?
// something like:
// this.set("searchResult.options.transport.read.data.postId", this.get("searchId"));
this.set("searchResult", new kendo.data.DataSource({
transport: {
read: {
url: "http://jsonplaceholder.typicode.com/comments",
dataType: "jsonp",
data: {
postId: this.get("searchId")
}
}
}
}));
}
});
kendo.bind($("#myView"), viewModel);
.item {
list-style: none;
}
.item span {
display: inline-block;
min-width: 40px;
}
#myListView {
min-height: 50px;
}
<link href="https://kendo.cdn.telerik.com/2016.1.112/styles/kendo.common.min.css" rel="stylesheet" />
<link href="https://kendo.cdn.telerik.com/2016.1.112/styles/kendo.default.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2016.1.112/js/kendo.all.min.js"></script>
<div id="myView">
<label>Enter Post ID (1,2,3,4...)
<label>
<br/>
<span class="k-textbox k-space-right">
<input type="text" data-value-update="keyup" data-bind="value: searchId, events: {keyup: searchFnc}"/>
</span>
<ul id="myListView" data-role="listview" data-bind="source: searchResult" data-template="template-search-result">
</ul>
</div>
<script type="text/x-kendo-template" id="template-search-result">
<li class="item">
<span>#: postId #</span>
<span>#: id #</span>
<span>#: name #</span>
</li>
</script>

What about this? change-datasource-url-on-grid. It is using a function as similar as yours ( options.transport.read.url ) from kendo. Then it is updated with .refresh().

This is how i would do it fiddle
var viewModel = kendo.observable({
searchId: 1,
searchResult: new kendo.data.DataSource({
transport: {
read: {
url: function() {
return "https://jsonplaceholder.typicode.com/" + viewModel.get("searchId") + "/comments"
},
dataType: "jsonp"
}
}
}),
searchFnc: function() {
this.searchResult.read();
}
});
kendo.bind($("#myView"), viewModel);

Related

create observables dynamically and show it in html ,knockout?

HTML :-
<div class="row" style="margin-left: 10px;" data-bind="foreach: {data: data, as: 'data1'}">
<span style="color: red; display: none;" data-bind="attr:{'id':data1.mandatory!=0?'id'+data1.dynamicid:''},text: 'You have selected ' +app.vm.observables.totalSelected()+ ' Observation areas. Please restrict to only 2.'"></span>
</div>
here the observable is same for every div element id so value is showing same how to do it dynamically?
JAVASCRIPT :-
`$('#id'+dynamicid+' input:checkbox.paramValues:checked').each(function(e){
DataImprove++;
});`
if(DataImprove>2){
vm.observables.totalSelected(DataImprove);
}
Need to create observables dynamically based on the div element ids and show it in the frontend HTML.
I'm not entirely sure I understand what you are trying to do, but hopefully this helps
I think it would make sense to move some of the functionality out out the view and into a viewModel
var externalData = [{
mandatory: false,
dynamicid: 1,
}, {
mandatory: false,
dynamicid: 2,
}, {
mandatory: 1,
dynamicid: 3,
}, {
mandatory: false,
dynamicid: 4,
}];
function ViewModel() {
var self = this;
self.data = ko.observableArray([]);
self.totalSelected = ko.pureComputed(function() {
return self.data().filter(function(i) {
return i.selected() === true;
}).length;
});
self.selectedText = ko.pureComputed(function(){
return 'You have selected ' + self.totalSelected() + ' Observation areas.';
});
var mappedData = externalData.map(function(item) {
return {
mandatory: item.mandatory,
dynamicid: item.dynamicid,
selected: ko.observable(false),
mandatoryStatus: item.mandatory == true ? 'mandatory' : ''
};
});
self.data(mappedData);
}
var vm = new ViewModel();
ko.applyBindings(vm);
.mandatory {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<span data-bind="text: selectedText"></span>
<ul data-bind="foreach: {data: data, as: 'data1'}">
<li data-bind="class: mandatoryStatus">
<label data-bind="text: dynamicid"></label>
<input type="checkbox" data-bind="checked: selected" />
</li>
</ul>

Kendo ListView: include a href

I am using Kendo ListView with remote datasource. I would like to add links to the data that is displayed but I am struggling.
Here is my function:
$(function () {
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: URL + "/Read",
dataType: "json"
}
},
schema: {
data: function (response) {
return response.Data["dsStudent"]["ttStudent"];
},
},
});
$("#listView").kendoListView({
dataSource: dataSource,
selectable: "multiple",
dataBound: onDataBound,
change: onChange,
template: kendo.template($("#template").html())
});
function onDataBound() {
//console.log("ListView data bound");
}
function onChange() {
var data = dataSource.view(),
selected = $.map(this.select(), function (item) {
return data[$(item).index()].fileID;
});
console.log("Selected: " + selected.length + " item(s), [" + selected.join(", ") + "]");
}
});
Here is my template
<script type="text/x-kendo-tmpl" id="template">
<div class="product">
<ul class="list-group">
<li class="list-group-item">#:Name#</li>
</ul>
</div>
</script>
The data is displayed as expected. My JSON contains a value that I would like to append to a url, this would then be used to create the href link. This is where I am struggling.
I have been able to console.log the value I need form my JSON but I am lost trying to figure out how to create the href.
Here is a snippet of my JSON:
{"Data": {"dsStudent": {"ttStudent": [{"studentNum": 366,"studentVersion": 2,"createDate": "2018-02-11","fileID":"18525478387e8","description":"StudentNames.pdf","displayCreateTime": "15:31"}]}}}
Using the onChange function, I am able to console.log the required field from the JSON.
I am trying to output the results like this, the fileID would change for each record in the JSON file.
<ul>
<li>
Download Student Record
</li>
</ul>
I hope I have been able to explain where I am struggling.
Just do like in your first template, print the value:
Download Student Record
^ here is where you print the fileId inside the link address

Why kendo.observable do not read datasource

Could you explain why kendo ui observable do not read data source when bind to html ?
I based my code on this example : http://demos.telerik.com/kendo-ui/mvvm/remote-binding
I don't understand the link between the dropdown and the observable.
InitObservable = function (Id) {
viewModel = kendo.observable({
//create a dataSource
tacheDataSource: new kendo.data.DataSource({
autoSync: true,
transport: {
read: {
url: function () {
return crudServiceBaseUrl + "/Taches?ID=" + Id;
},
method: "GET",
dataType: "json"
}
,
update: {
url: crudServiceBaseUrl + "/Taches",
method: "PATCH",
dataType: "json"
}
,
destroy: {
url: crudServiceBaseUrl + "/Taches/Destroy",
dataType: "json"
}
,
create: {
url: crudServiceBaseUrl + "/Taches",
method: "POST",
dataType: "json"
}
,
parameterMap: function (options, operation) {
if (operation !== "read" && options.models) {
return { models: kendo.stringify(options.models) };
}
}
},
batch: true,
pageSize: 20,
schema: {
model: {
id: "ID",
fields: TacheFields
}
}
}), // endDatasource
selectedTache: null, //this field will contain the edited dataItem
hasChange: false,
save: function (e) {
this.tacheDataSource.sync();
this.set("hasChange", false);
},
remove: function () {
if (confirm("Etes vous sûr(e) de vouloir supprimer cette tâche ?")) {
this.tacheDataSource.remove(this.selectedTache);
this.set("selectedTache", this.tacheDataSource.view()[0]);
this.change();
}
},
showForm: function () {
return this.get("selectedTache") !== null;
},
change: function () {
this.set("hasChanges", true);
}//,
//cancel: function () {
// this.dataSource.cancelChanges(); //calcel all the change
// validator.hideMessages(); //hide the warning messages
// $("#tacheWindow").data("kendoWindow").close();
//}
});
kendo.bind($("#tacheWindow"), viewModel);
}
I tested the datasource alone with datasource.read(), it works.
What is the trigger of the read of the datasource ?
----- New details
I added
type: "odata-v4"
in the datasource and I updated the schema as this :
e
schema: {
data:function(data){
var toReturn = data.value;
return toReturn;
},
model: {
id: "ID",
fields: TacheFields
}
}
And this to force read()
viewModel.selectedTache = proprietesEcranTache.tacheId;
if (viewModel.showForm()) {
viewModel.tacheDataSource.read();
kendo.bind($("#tacheWindow"), viewModel);
}
I see my answer in network debugger of chrome and I know I receive data in the form witout error but no data are displayed.
Here the oData answer
{
"#odata.context":"http://localhost:14986/odata/$metadata#Taches","value":
[
{
"ID":1,"Description":"D\u00e9marrage application","CreateurId":7,"TypeTacheID":1,"EtatTacheID":6,"ValidantId":null,"DateValidation":null,"EstValidee":false,"CommentaireValidation":null,"EvennementPrecedentID":null
}
]
}
Here is my form
<div id="tacheWindow">
<form id="TacheForm">
<ul class="TacheFormFields">
<li class="">
<div class="formFieldTitle">Id</div>
<div class="formFieldInput textField"><input id="tacheId" type="text" data-bind="value: ID" /></div>
</li>
<li>
<div class="formFieldTitle">Type de tâche</div>
<select id="typesTachesDdl" data-role="dropdownlist"
data-bind="value: TypeTacheID"
data-value-primitive="true"
data-text-field="Nom"
data-value-field="ID"></select>
</li>
<li>
<div class="formFieldTitle">Description</div>
<div class="formFieldInput textField">
<input type="text" data-bind="value: Description" />
</div>
</li>
<li>
<div class="formFieldTitle">Createur</div>
<select id="CreateursDdl" data-role="dropdownlist"
data-bind="value: CreateurId"
data-value-primitive="true"
data-text-field="Nom"
data-value-field="ID"></select>
</li>
<li>
<div class="formFieldTitle">Validant</div>
<select id="ValidantsDdl" data-role="dropdownlist"
data-bind="value: ValidantId"
data-value-primitive="true"
data-text-field="Nom"
data-value-field="ID"
disabled="disabled"></select>
</li>
</ul>
<div class="dialog_buttons">
<button id="TacheFormTemplateSave" data-bind="click: observableSave" class="k-button">Ok</button>
<button id="TacheFormTemplateSave" data-bind="click: observableCancel" class="k-button">Annuler</button>
</div>
</form>
Placing the datasource within your view model simply makes it observable and nothing more, as you have noted. It will only get read when passed to a kendo widget (such as a DropDownList). The telerik demo shows this within the bound html container:
<select data-role="dropdownlist" data-option-label="Select product"
data-value-field="ProductID" data-text-field="ProductName"
data-bind="source: productsSource, value: selectedProduct" style="width: 100%;"></select>
The kendo.bind statement scans the html container for elements with a data-role attribute. In the case above it will find data-role="dropdownlist", instantiate a DropDownList widget and add the necessary html elements for it to the DOM. This part of the declaration:
data-bind="source: productsSource"
...will search for a datasource named 'productsSource' within the view model and assign it to the DropDownList as its datasource to use. The DropDownList will then trigger a read of that datasource in order to populate itself with data.
I created a simple sample that works
Home Page
<div id="editForm">
<table>
<tr>
<td>Id</td>
<td>Nom</td>
</tr>
<tr>
<td>
<input data-role="dropdownlist"
data-auto-bind="false"
data-text-field="Nom"
data-value-field="ID"
data-bind="value: selectedPerson,
source: persons,
visible: isVisible,
enabled: isEnabled,
events: {
change: onChange
}"
style="width: 200px;" />
</td>
<td><input type="text" data-value-update="displaySelectedPerson" data-bind="value: selectedPerson.Nom" class="k-textbox" /></td>
</tr>
</table>
</div>
Important detail : in the text box : data-bind="value: selectedPerson.Nom"
This allow observable to update the field.
Javascript :
var persons = [
{ ID: "1", Nom: "Lolo" },
{ ID: "2", Nom: "Toto" }
];
documentReady = function () {
var viewModel = new kendo.observable({
personsSource: persons
, persons: new kendo.data.DataSource({
data: persons,
schema: {
model: {
fields: {
ID: { type: "number" }
, Nom: { type: "string" }
}
}
}
})
, selectedPerson: null
, hasChange : false
, isPrimitive: false
, isVisible: true
, isEnabled: true
, primitiveChanged: function () {
this.set("selectedPerson", null);
}
, onChange: function () {
console.log("event :: change (" + this.displaySelectedPerson() + ")");
}
, displaySelectedPerson: function () {
var selectedPerson = this.get("selectedPerson");
return kendo.stringify(selectedPerson, null, 4);
}
});
kendo.bind($("#editForm"), viewModel);
}

I want to filter in the list if the text box value is changed using knockout

I want to filter in the list if the text box value is changed if the
JSON Returned in Ajax call is as I am using two different model.
Filteration should show hide or just filter the data I am providing you the JSON data what I am getting from the ajax call. Thanks
Data = [{"code":"Grand Financial","cls":"Branch","Chk":true},{"code":"Joan Group","cls":"Branch","Chk":true}]
var searchModel, advisorGroupModel;
$(document).ready(function () {
$.ajax({
type: "GET",
url: '/ASPNET/Reports/GetAdvisorGroups',
dataType: "json",
success: function (data) {
advisorGroupModel = {
advisorGroup: ko.observableArray(data)
};
ko.applyBindings(advisorGroupModel, document.getElementById("advisorGroupModel"));
}
})
var searchModel = {
searchQuery: ko.observable('')
};
searchModel.searchHandle= ko.dependentObservable(function () {
var code = this.searchQuery().toLowerCase();
return ko.utils.arrayFilter(advisorGroupModel, function (beer) {
debugger;
return beer.code.toLowerCase().indexOf(code) >= 0;
});
console.log(search);
}, searchModel)
ko.applyBindings(searchModel, document.getElementById("searchModel"));
});
<div id="searchModel">
<input data-bind="value: searchQuery, valueUpdate: 'keyup'" />
<h6 data-bind="text: searchQuery"></h6>
</div>
<div class="CheckBoxListGroup" id="advisorGroupModel">
<ul data-bind="template: { name: 'advisorGroupTemplate', foreach: advisorGroup, as: 'singleAdvisorGroup' }"></ul>
<script type="text/html" id="advisorGroupTemplate">
<li>
<input type="checkbox" data-bind="attr: { value: code, id: code, checked: Chk }" name="GroupsSel">
<label data-bind="attr: { for: code }, text: '' + code + ' (' + cls + ')' "></label>
</li>
</script>
</div>
don't bind your display to the entire list, bind your display to a computed function that returns the filtered list or returns all items when there are no filters.
then on your keyup call your filterlist function that filters the list removing the ones that do not match your filter

How to bind data from two tables in PhoneJs?

I have two tables:
nom_articole { id(PK), denumire, nom_um_id(FK) }
nom_um { id(PK), simbol, denumire }
I want to display:
nom_articole.id
nom_articole.denumire
nom_um.simbol
My html code:
<div data-options="dxView : { name: 'nom_articoleDetails', title: 'Nom_articole' } " >
<div data-options="dxContent : { targetPlaceholder: 'content' } " >
<div data-bind="dxScrollView: { }">
<h2 data-bind="text: nom_articole.denumire"></h2>
<div class="dx-fieldset">
<div class="dx-field">
<div class="dx-field-label">ID</div>
<div class="dx-field-value" data-bind="text: nom_articole.id"></div>
</div>
<div class="dx-field">
<div class="dx-field-label">Denumire</div>
<div class="dx-field-value" data-bind="text: nom_articole.denumire"></div>
</div>
<div class="dx-field">
<div class="dx-field-label">U.M.</div>
<div class="dx-field-value" data-bind="text: ????????????????"></div>
</div>
</div>
<div data-options="dxContentPlaceholder : { name: 'view-footer', transition: 'none' } " ></div>
</div>
</div>
My Javascrip code:
MobileApplication.nom_articoleDetails = function(params) {
return {
id: params.id,
//nom_um: new MobileApplication.nom_umViewModel(),
nom_articole: new MobileApplication.nom_articoleViewModel(),
handleDelete: function() {
DevExpress.ui.dialog.confirm("Are you sure you want to delete this item?", "Delete item").then($.proxy(function (result) {
if (result)
this.handleConfirmDelete();
}, this));
},
handleConfirmDelete: function() {
MobileApplication.db.nom_articole.remove(params.id).done(function() {
MobileApplication.app.navigate("nom_articole", { target: "back" });
});
},
viewShown: function() {
nom_articoleDetails = this;
MobileApplication.db.nom_articole.byKey(params.id).done(function(data) {
nom_articoleDetails.nom_articole.fromJS(data);
});
}
};
This code was generated by Devexpress multi-channel application wizard.
From the information you gave, and provided that nom_articole and nom_um share the same key, the code would be:
viewShown: function() {
// ... your code ...
MobileApplication.db.nom_um.byKey(params.id).done(function(data) {
nom_articoleDetails.nom_um.fromJS(data);
});
}
You uncomment the nom_um member and use text: nom_um.simbol as the binding text in the view.
Update:
To load an object by foreign key, you have two options. The first is cascading fetches:
MobileApplication.db.nom_articole.byKey(19).done(function (data) {
nom_articoleDetails.nom_articole.fromJS(data);
MobileApplication.db.nom_um.byKey(data.nom_um_id).done(function(data) {
nom_articoleDetails.nom_um.fromJS(data);
});
});
The second will work if your data service is properly configured OData. In this case you may use the expand feature:
MobileApplication.db.nom_articole.byKey(19, { expand: "nom_um" }).done(function (data) {
// data will contain a nested object
});
P.S. DevExpress provides Support service, and in case you cannot find the right answer here, you can ask them and share the solution.

Categories

Resources