Kendo MVVM - Bind to ENTIRE View Model - kendo-ui

I have a situation where I am wanting to observe the behavior of a view model as I am populating a form. I can do this with defining a lot of fields that look kind of like the model, and binding to them, but that is kind of messy.
I am currently accomplishing this with the following code;
(function ($) {
$.printJSON = function(value){
return JSON.stringify(value, undefined, 2);
}
})(jQuery);
var viewModel = kendo.observable({
// other fields etc
update: function (e) {
e.preventDefault();
$("#json_result").html($.printJSON(this));
}
});
<div style="width: 400px; float: left; padding-left: 15px;" >
<button data-bind="click: update" value="Update" >Update</button>
<pre id="json_result">
</pre>
</div>
So you click the button, and it runs the function to draw the view model JSON to the screen, all nice and formatted.
But this still requires a button click. While that isn't that big of a problem for me, since this isn't something I need for a lot of situations, is there any way to actually do this and have it update when the view model changes in any way? I tried to just bind to the function and it never updates without an explicit call, I tried binding right to the view model, and that didn't work either.

You could either simply bind the change event:
viewModel.bind("change", function (e) {
$("#json_result").html($.printJSON(this));
});
or you could use a calculated field:
var viewModel = kendo.observable({
field1: "field1",
field2: "field2",
field3: "field3",
print: function () {
// need to register for all fields so that the change event for print is triggered
for (var fieldName in this) {
if (this.hasOwnProperty(fieldName)) {
this.get(fieldName);
}
}
return $.printJSON(this.toJSON());
}
});
and bind to it with:
<pre data-bind="html: print">
See fiddle demonstrating both methods: http://jsfiddle.net/lhoeppner/S2WeB/

Related

With knockout foreach binding to TBODY, how to show loading animation during and AFTER ajax call

User makes repeated queries against database over the course of the day; each time, the results are cleared from the table and new data are injected into the table:
<tbody data-bind="foreach: MyVM.Results">
and in code before the ajax call:
MyVM.Results.removeAll();
I want to display an animated spinner of some kind while the ajax call is underway (Edit: and then also when ko is still working on creating the table rows after the ajax call returns).
EDIT: What is "the knockout way" of displaying this animation when there's a standard ajax call with fail and success callbacks, and the tbody is foreach-bound to the observableArray Results?
EDIT2: configuring the Ajax call itself in jQuery with beforeSend and complete callbacks does not solve the problem entirely because taking UI action when the ajax call itself is complete does not account for the delay of knockout's for-each binding of the data to the table. is there a knockout event that signals "binding complete"?
EDIT3: The answers are not understanding the problem. My fault for trying to make it simple and leaving out a lot of code. This has nothing to do with Ajax. Consider this very simple scenario, which is exaggerated to make the problem clearer. Let's say you have an array with a million items in it. Ajax call is already completed! Now you want to get the items in that array into a ko observableArray to which your TABLE TBODY is bound with for-each binding. This binding process itself is going to take some seconds to complete We want to hide our animation after the binding has finished and something is displaying on the HTML page. Is there a way to know that the table rows created by knockout have begun to be rendered in the UI?
I developed a custom loading animation for doing this.
<!--Preloader-->
<div id="preloader">
<div class="preloader" data-bind="visible: _isShow">
<div class="loader-content">
<img src="img/ajax-loader.gif" alt="Loading.." style="margin: 0px auto 20px auto;">
<br>
<span class="loader-txt">Loading... Please wait....</span>
</div>
<!--End of loader-content-->
</div>
<!--End of preloader-->
</div>
CSS codes
/*****************Preloader******************/
.preloader {
background: rgba(0, 0, 0, 0.9);
width: 100%;
position: fixed;
z-index: 10000;
top:0;
bottom:0;
left:0;
right:0;
}
.preloader-hidden{
visibility: hidden;
}
.preloader .loader-content {
text-align: center;
top: 50%;
margin-top: -22px;
position: absolute;
left: 50%;
margin-left: -75px;
}
.loader-txt {
font-size: 14px;
color: #fff;
vertical-align: middle;
margin-left: 15px;
}
Javascript Code for preloader viewmodel
function PreloaderViewModel() {
var self = this;
self._isShow = ko.observable(false);
self.ShowPreloader = function() {
self._isShow(true);
};
self.HidePreloader = function() {
self._isShow(false);
};
}
Register the view model as bellow
var preloaderVM;
if ($.isEmptyObject(preloaderVM)) {
preloaderVM = new PreloaderViewModel();
ko.applyBindings(preloaderVM, document.getElementById("preloader"));
preloaderVM.HidePreloader();
}
Use it in ajax call like bellow.
//Show preloader
preloaderVM.ShowPreloader();
$.ajax({
type: "GET",
dataType: "json",
url: yourServiceUrl,
data: searchdata,
success: function (data) {
//do whatever in data return from ajax call
//Hide preloader
preloaderVM.HidePreloader();
},
error: function (error) {
console.log(error.responseText);
preloaderVM.HidePreloader();
}
});
If you want to change the text showing in pre-loader by defining a property on preloaderviewModel.
ko way is to use model to drive the view.
If the standard ko bindings are not enough (for instance, if gif animation is not enough for you), create a customised ko.bindingHandlers.
An idea ko app hides all DOM manipulation inside ko.bindingHandlers.
Here is a template that I use for ajax data loading.
HTML
<!-- ko if: loading -->
<!-- show spinner -->
<!-- /ko -->
<!-- ko ifnot: loading -->
<!-- show result, your data-bind="foreach: Results" -->
<!-- /ko -->
Javascript
//assume you use self to hold 'this' pointer in viewModel constructor
self.loading = ko.observable(false);
// in your data loading action
self.loadRemoteData = function() {
//start loading
self.loading(true);
$.ajax({
// ...
success: function(data) {
// update Results(data);
},
fail: function() { ...},
complete: function() {
//finish loading
self.loading(false);
}
});
};
I found the answer. Instead of looping through the Ajax data and adding an object to the ko observableArray on each iteration, I have to pop or shift() each item off the Ajax data array and push it onto the observableArray in a custom event using trigger(). The eventhandler invokes the custom event again and again while data contains items. Thus, the UI is not blocked but table rows begin to appear immediately.
In my case, the web app is running on an intranet, and the local database can return 10,000 rows on the LAN in the blink of an eye, but it takes a good number of seconds for all 10,000 rows to be created in the HTML Table using knockout for-each binding. With the event approach, the rows start becoming visible to the user instantly.
$(document).on("PushIt", function (event, data, results) {
var item = data.shift();
var Cust = new Customer(
item["firstname"],
item["lastname"],
item["addr1"],
item["city"],
item["state"],
item["zipcode"]
)
results.push(Cust);
if (data.length > 0) {
// timeout avoids recursion-limit problems
setTimeout(function () { $(document).trigger("PushIt", [data, results]); }, 1);
}
});

Keypress custom binding on input still not worked in kendo ui mvvm

I think my question is similar with this. However, event keypress on input text still not worked.
My Question here is how to add custom binding into input text box and trigger 'something' when pressing enter button.
Here is another sample when the target is kendo widget; and it's working.
HTML code:
<div id="app">
<input type="text" data-bind="keyPress: onKeyPress" />
<div id="output"></div>
</div>
Java script code:
kendo.data.binders.keyPress = kendo.data.Binder.extend({
init: function (element, bindings, options) {
kendo.data.Binder.fn.init.call(this, element, bindings, options);
var binding = this.bindings.keyPress;
$(element.input).bind("keypress", function (e) {
if (e.which == 13) {
binding.get();
}
});
},
refresh: function () { }
});
var viewModel = kendo.observable({
onKeyPress: function () {
$("#output").append("<div>keyPress</div>");
}
});
kendo.bind($("#app"), viewModel);
Jsfiddle code:
http://jsfiddle.net/ikomangmahendra/4uL8Y/2/
Thanks in advance
The problem was connected with the following line:
before:
$(element.input).bind("keypress", function (e) {
after:
$(element).bind("keypress", function (e) {
I should bind the event to the element, not to element.input.

Knockout-Kendo RadialGauge pointer transition not working

Can anyone explain why this
js:
var ViewModel = function() {
this.myValue = ko.observable(25);
};
ko.applyBindings(new ViewModel());
html:
<div data-bind="kendoRadialGauge: myValue"> </div>
will allow the pointer to transition nicely to the new value, when the databound value changes.
However when passing additional options, like this
js:
var ViewModel = function() {
this.myValue = ko.observable(25);
//various gauge settings omitted for brevity
this.pointerOptions = ko.computed(function() {
return { color: this.pointerColor(), value: this.myValue() };
}, this);
};
ko.applyBindings(new ViewModel())
html:
<div data-bind="kendoRadialGauge: { value: myValue, gaugeArea: gaugeOptions, pointer: pointerOptions }"> </div>
...the pointer just jumps immediately to the new value.
Knockout 2.3.0, JQuery 2.0.3, Kendo UI Dataviz 2013.2.716
When you are specifying any of the KO "tracked" options (gaugeArea, pointer, scale) the gauge gets re-drawn by KO with using the Kendo's redraw method.
In itself it shouldn't cause the lost of the transition but KO also slightly changes the gauge's value which causes the transition lost.
Source on github:
this.value(0.001 + this.value());
Removing this line from the source code fixes your problem, so I would say this is bug in Knockout-Kendo.

Angular ng-click on inputed later on dom

i'm changing a innter html of a dom element with a button. And when button is clicked i want to fire another controller function. Something like that. ... But is not working :).
$scope.addBtn = function() {
$('domtarget').html('<button ng-click="removeButton();"></button>');
}
$scope.removeBtn = function() {
$('domtarget').html('');
}
Please suggest fix :)
Do not modify DOM inside your controller, ever.
<div ng-show="showMe"></div>
<button ng-click="showMe = !showMe;anotherAction()">Switch</button>
<button ng-click="someOtherAction()">Switch2</button>
.
function SomeCtrl($scope) {
$scope.showMe=true;
$scope.anotherAction = function () {
alert("gotcha");
};
$scope.someOtherAction = function () {
$scope.showMe = !$scope.showMe;
$scope.anotherAction();
};
}
For hiding/showing an element conditionally, use ng-show or ng-hide.
For firing an event on click, use ng-click

Edit pop up box for a grid design

I am writing a MVC3 project. Right now I have a table which has column with Data as actionLinks as:
<td style="color: Black; background-color: Bisque; text-align: center; width: 410px">
#Html.ActionLink(#item.LookUp_NameString, "EditPartial", "Capitation", new { id = item.CAPITATION_RATE_ID }, new { #class = "actionLink" })
</td>
EditPartial as the name suggests is a partial view, which I need to be opened as a pop-up menu so that user can edit the details of the object, save it and we can come back to original page.
I have tried the render partial, but can't get it to pass the id value dynamically.
This is for edit functionality of my grid. What will be the best way to implement this?
If you want to open the result of EditPartial Action method in a model popup, you need some model popup code for that.
jQuery UI is one option. http://jqueryui.com/demos/dialog/
1) Include jQuery UI reference in your page,
2) Add the below script to your page which will convert your normal link to a model popup
<script type="text/javascript">
$(function(){
$(".actionLink").click(function (e) {
var url = this.href;
var dialog = $("#dialog");
if ($("#dialog").length == 0) {
dialog = $('<div id="dialog" style="display:hidden"></div>').appendTo('body');
}
dialog.load(
url,
{}, // omit this param object to issue a GET request instead a POST request, otherwise you may provide post parameters within the object
function (responseText, textStatus, XMLHttpRequest) {
dialog.dialog({
close: function (event, ui) {
dialog.remove();
},
modal: true,
width: 460, resizable: false
});
}
);
return false;
});
});
</script>
From your action result, you can return whatever markup you want to show in the Model popup. Mostly you will be returning a View. If you want to show a partial View,If it is an ajax request and show the normal view if it is a normal request, you can check the Request.IsAjaxRequest method to do that.
public ActionResult EditPartial(int id)
{
CustomerViewModel objCustomer=GetCustomer(id);
if(Request.IsAjaxRequest())
{
return View("Partial/Edit",objCustomer);
}
return View(objCustomer);
}
Assuming you have 2 views present to show your normal page and partial page (for model popup)
I prefer to name my action method as Edit instead of EditPartial, because it is handling both requests (ajax and normal)

Resources