Kendo Grid MVVM with rowtemplate binding to events error - javascript

I´m trying to bind and event inside a RowTemplate to a viewModel function, using Kendo Grid MVVM.
However, after calling kendo.bind an error is displayed in then console, and the event does not get fired, however the grid displays correctly. Here is the error:
Uncaught Error: The mouseover binding is not supported by the button element kendo.editor.js:890
I tried to change the element type inside the row template to any other thing, with same results.
Here is my html code:
<div id="content">
<div>
<div id="grid" data-role="grid" data-bind="source: ordersSource"
data-selectable="True" data-columns='["OrderID", "ShipName", "ShipCity"]' data-row-template="rowTemplate" />
</div>
</div>
<script id="rowTemplate" type="text/x-kendo-template">
<tr data-uid="#= uid #">
<td><button data-bind="mouseover: listener">#: OrderID #</button></td>
<td>#: ShipName #</td>
<td>#: ShipCity #</td>
</tr>
</script>
And here is my viewModel code:
var ordersDatasource = new kendo.data.DataSource({
type: "odata",
transport: {
read: "http://demos.kendoui.com/service/Northwind.svc/Orders"
},
schema: {
model: {
id: "OrderID",
fields: {
OrderID: { type: "number" },
ShipName: { type: "string" },
ShipCity: { type: "string" }
}
}
},
pageSize: 5,
});
var viewModel = kendo.observable({
ordersSource: ordersDatasource,
listener: function (e) {
alert("Event: " + e.type);
}
});
kendo.bind($('#content'), viewModel);
Here is the jsFiddle if you want to try.
The first column button should fire the event when passing the mouse over it, however it does not.

The correct syntax to bind events is:
<button data-bind="events: { mouseover: listener }">#: OrderID #</button
(updated demo)

Related

why won't jquery datatable respond to click?

I have a jquery datatable that populates from ajax but when I click on a row, the table click event handler does not fire. Here is my datatable:
function initDataTables(watchlist) {
$('#watchlistTable').DataTable({
ajax: {
url: "/MoneyMachine/getWatchlist.php",
type: "post",
data: {watchlist:watchlist}
},
columns: [
{ data: 'Symbol' },
{ data: 'CompanyName' },
{ data: 'ClosePrice', class: 'text-right' },
{ data: 'PricePctChangeToday', class: 'text-right'},
{ data: 'CAGR', class: 'text-right'},
{ data: 'BenchmarkCAGR', class: 'text-right'},
{ data: 'DivYield', class: 'text-right'},
{ data: 'ExDivDate'},
{ data: 'AppreciationPotential', class: 'text-right'}
],
responsive: true, //supposedly make table clickable but does nothing
destroy: true //A data table can only be initialized once. It must be destroyed so it can be initialized again.
});
}
I've tried a couple different click events like this:
$('.dataTable').on( 'click', '.dataTable', function () {
console.log("watchlistTable was clicked");
});
And like this:
$('#watchlistTable tbody').on( 'click', 'tr', function () {
console.log("watchlistTable was clicked");
});
And like this:
$('.display').on( 'click', '.display', function () {
console.log("watchlistTable was clicked");
});
But neither one fires. Here is the html for it:
<table id="watchlistTable" class="display" style="width:100%">
<thead>
<tr>
<th>Sym</th>
<th>Company Name</th>
<th>Price</th>
<th>Change%</th>
<th>CAGR</th>
<th>Benchmark<br>CAGR</th>
<th>Div<br>Yield%</th>
<th>Ex-Div<br>Date</th>
<th>App<br>Pot%</th>
</tr>
</thead>
</table>
My guess is you aren't including a <tbody> in the original html
Try adding it to the target selector and delegating to the table itself instead
$('#watchlistTable').on( 'click', 'tbody tr', function () {...
Note that $('.dataTable').on( 'click', '.dataTable', ... is trying to delegate to an existing class dataTable and would only be triggered on other elements with that class that are inside it. Since nothing in the html shown has that class it's not clear what that element would even be and I doubt you have nested elements with same class

dynamically add/remove image in vue.js

var loaderGif = "https://www.tietennis.com/img/loaders/LoaderIcon.gif"
var processingImageUrl = '<img id="imgProcessing" src="' + loaderGif + '" />'
$(document).on("click", "input[name='PermissionID']", function() {
var PermissionCheckBox = $(this)[0];
$.ajax({
method: "POST",
url: "https://httpbin.org/post",
cache: false,
async: true,
beforeSend: function(xhr, opts) {
$(PermissionCheckBox).after(processingImageUrl);
},
success: function(result) {
$(PermissionCheckBox).parent().find('#imgProcessing').remove();
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td>
Check me:
<input name="PermissionID" type="checkbox" value="1">
</td>
</tr>
</table>
I was actually trying to convert the jQuery code to vue.js.
I am trying to find a way if I could put the image with checkbox on click in vue.js.
I tried below code, but now sure how could I use event passed from checkbox to add image and remove it
updatePermission(roleModulePermissionID, event) {
}
Can you suggest something for this?
In Vue, you (optimally) don't directly manipulate the DOM. You manipulate the data and configure the template to react to that data according to what you need.
To create multiple rows, use v-for.
So, for instance, instead of adding and removing a "loading image", you would create an <img> whose display depended on some flag from your data, say permission.loading:
<img v-show="permission.loading" :src="loadingImg">
That way, when you set permission.loading to true, the loading image will show. When you set permission.loading to false it will hide.
Since you want to show it while the Ajax is performing, set permission.loading to true before calling the Ajax (the fetch() below) and set permission.loading to false when it completes.
Full demo below.
new Vue({
el: '#app',
data: {
loadingImg: "https://www.tietennis.com/img/loaders/LoaderIcon.gif", // for demo purposes
permissions: [{
id: 1,
label: 'Permission to Take off',
ticked: false,
loading: false,
postURL: "https://httpbin.org/post?take-off" // demo URL
},{
id: 2,
label: 'Permission to Board',
ticked: true,
loading: false,
postURL: "https://httpbin.org/post?board" // demo URL
},{
id: 3,
label: 'Permission to Land',
ticked: false,
loading: false,
postURL: "https://httpbin.org/post?land" // demo URL
}]
},
methods: {
updatePermission(permission) {
permission.loading = true; // set loading and image will be shown
fetch(permission.postURL, {method: "POST", body: {}})
.then(() => permission.loading = false); // setting to false will make it disappear
}
}
})
img { height: 17px; margin-bottom: -1px; }
<script src="https://unpkg.com/vue"></script>
<div id="app">
<table>
<tr v-for="permission in permissions">
<td>
<label>
{{ permission.label }}:
<input name="PermissionID" type="checkbox" :value="permission.id" #change="updatePermission(permission)" v-model="permission.ticked" :disabled="permission.loading">
</label>
<img v-show="permission.loading" :src="loadingImg">
</td>
</tr>
</table>
</div>
I also would add a :disabled="permission.loading" to prevent another click when it is loading.

Kendo UI Grid change row detail values from command function without detail collapse

I have a kendo grid with a detail template, which I wish to clear if the user clicks on the clear command in the parent row.
I managed to get this to work, but as soon as I set the value on the dataItem, the row detail collapses, which causes the user to loose his place.
function clearDetails(e) {
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
dataItem.set("City",""); // causes row detail collapse
}
$(document).ready(function () {
$("#grid").kendoGrid({
dataSource: {
type: "odata",
transport: {
read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Customers"
},
},
columns: [{
field: "ContactName",
title: "Contact Name",
width: 240
}, {
field: "Country",
width: 150
}, { command: { text: "Clear", click: clearDetails }, title: " ", width: "180px" }],
detailTemplate: kendo.template($("#myRowDetailTemplate").html())
})
});
Working example:
https://jsbin.com/xuwakol/edit?html,js,output
Is there a way I can still clear the values in the row detail, without it collapsing.
I had the same issue I got around it by using the dataBinding function within the kendo grid.
Basically it checks for an item change event and will cancel the default action to close the grid. This allowed me to continue to use the set method.
Example:
$("#grid").kendoGrid({
dataBinding: function (e) {
if (e.action == "itemchange") {
e.preventDefault();
}
},
});
}
I managed to get this right by not using the set method on the dataItem. http://docs.telerik.com/kendo-ui/api/javascript/data/observableobject#methods-set
I just changed the value on the dataItem, dataItem.City =""; and with the help of jquery selectors cleared the value of the textarea.
function clearDetails(e) {
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
dataItem.City ="";
$(e.currentTarget).closest(".k-master-row").next().find("textarea[name='City']").val("");
}

Updating server from Kendo Color picker inside kendo grid

The Problem
So i am currently trying to implement a color picker inside of a Kendo grid, that will hopefully send the chosen color to my Sql Table. Unfortunately, It doesn't seem as though the Update controller is being reached. I am relatively new to Kendo UI, so there might be some incredibly dumb errors shown.
Questions
I guess my main question would be: How can i call the update method when update is clicked on the grid. Essentially, the color picker and the edit command are showing up in beautiful fashion. I just want to know how i can be sure that the method is being called when 'Update' is clicked, seeing as it is not reaching my controller. Feel free to ask if you need to see more code or perhaps a screen shot.
Code
Config.cshtml ( Grid )
#model IEnumerable<STZN.Models.AGCData.ErrorCode>
#{
ViewBag.Title = "Config";
}
#section HeadContent{
<script src="~/Scripts/common.js"></script>
<script>
$(document).ready(function () {
$("#grid").kendoGrid({
editable: "inline",
selectable: "row",
dataSource: {
schema: {
model: {
id: "error_code",
fields: {
color: { type: 'string' }
}
}
},
transport: {
read: {
type: "POST",
dataType: "json",
url: "#Url.Action("ErrorCodes")"
},
update: {
type: "POST" ,
dataType: "json",
url: "#Url.Action("UpdateErrorCodes")",
}
}
},
columns: [
{ command : [ "edit" ] },
{
field: "error_code", title: "Error Code",
},
{
field: "error_description", title: "Error Description"
},
{
field: "color",
width: 150,
title: "Color",
template: function (dataItem) {
return "<div style = 'background-color: " + dataItem.color + ";' </div>"
},
editor: function (container, options) {
var input = $("<input/>");
input.attr("color",options.field);
input.appendTo(container);
input.kendoColorPicker({
value: options.model.color,
buttons: false
})
},
}
]
});
});
</script>
}
Update Controller
public JsonResult UpdateErrorCodes(ErrorCode model)
{
using (var db = new AgcDBEntities())
{
db.Entry(model).State = System.Data.Entity.EntityState.Modified;
db.SaveChanges();
db.Configuration.ProxyCreationEnabled = false;
var data = db.ErrorCodes.Where(d => d.error_code == model.error_code).Select(x => new
{
error_code = x.error_code,
description = x.error_description,
color = x.color,
});
return new JsonResult()
{
JsonRequestBehavior = System.Web.Mvc.JsonRequestBehavior.AllowGet,
};
}
}
I actually managed to fix my issue by adding an additional input attribute to my editor function in the "color" field. It looks like this:
input.attr("data-bind","value:" + options.field);
There are still some present issues (unrelated to the fix/server update) , but as far as updating to the server, It work's as intended.

(Re)rendering Backbone view in change event handler does not work

I'm having two form elements, both 2-way-databinded via backbone.stickit.
The second form element (#input) is just cosmetics - there for showing it's actually working.
The idea is that my View gets (re)rendered,every time the option inside the dropdown (#select) menu gets changed.
I'm trying to achieve that by catching the the 'changed' event of #select and call this.render() to (re)render the view.
Apparently that doesn't work. The selected option doesn't get saved back into the model and I fail to understand why.
I'm not looking for a solution, rather than an explanation, why the following code doesn't work. The solution (as in: works for me) is part of the fiddle - commented out.
HTML:
<script type="text/template" id="tpl">
<h1>Hello <%= select %></h1>
<select id="select">
</select>
<p>Select:
<%= select %>
</p>
<hr>
<input type="text" id="input">
<p>Input:
<%= input %>
</p>
</script>
<div id="ctr"></div>
JavaScript:
Foo = Backbone.Model.extend({
defaults: {
select: "",
input: "",
}
});
FooView = Backbone.View.extend({
el: '#ctr',
template: _.template($('#tpl').html()),
initialize() {
this.model.bind('change', function() {
console.log("model change:");
console.log(this.model.get('select'));
console.log(this.model.get('input'));
}, this);
//this.model.bind('change:select', function() { this.render(); }, this); // <--------------------- WORKS
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
this.stickit();
return this;
},
events: {
'change #select': function(ev) {
console.log('change event triggered:');
console.log(this.model.get('select'));
console.log(this.model.get('input'));
this.render(); // <--------------------- DOES NOT WORK - WHY?
},
/* 'click #render': function(ev) {
console.log('render event triggered:');
console.log(this.model.get('select'));
console.log(this.model.get('input'));
this.render();
} */
},
bindings: {
'#input': 'input',
'#select': {
observe: 'select',
selectOptions: {
collection: function() {
return [{
value: '1',
label: 'Foo'
}, {
value: '2',
label: 'Bar'
}, {
value: '3',
label: 'Blub'
}]
}
}
},
},
});
new FooView({
model: new Foo()
}).render();
https://jsfiddle.net/r7vL9u07/9/
The reason it does not work to call this.render() from within your change #select event handler is because you are disrupting the two-way data binding that Backbone.stickit is providing you. The flow goes something like the following:
User changes the value of '#select'.
Your change #select handler fires and calls this.render().
render repopulates #ctr with a new select menu with no selected option.
Backbone.stickit responds to the change to #select.
Backbone.stickit tries to obtain the value of #select, but since it contains no selected option the value is undefined.
Backbone.sticket sets the model's select attribute to undefined.
The reason it works if you move the this.render() call to within the model's change:select handler is because Backbone.stickit is able to correctly update the model without the DOM changing before it gets the chance.

Categories