Filtering in Telerik Kendo Multiselect - javascript

Hi I have a simple select in my mvc view....
<select id="msProducts" multiple style="width:100%;"></select>
which is converted to a Kendo Multiselect using Javascript/JQuery
$(document).ready(function () {
//products multi-select
$("#msProducts").kendoMultiSelect({
placeholder: "Select Product(s)",
dataTextField: "ProductNameText",
dataValueField: "ProductNameValue",
dataSource: {
type: "json",
serverFiltering: true,
transport: {
read: {
url: "Home/Products"
}
}
}
});
});
My Contoller has:
'GET: Home/Products
<HttpGet>
Function Products() As JsonResult
Dim DiaryProductList As List(Of ProductsModel) = ProductsModel.GetProducts
Return Json(DiaryProductList , JsonRequestBehavior.AllowGet)
End Function
My ProductsModel Class is:
Public Class ProductsModel
Public Property ProductNameText As String
Public Property ProductNameValue As String
Public Shared Function GetProducts() As List(Of ProductsModel)
Dim ProductList = New List(Of ProductsModel)
Dim dc As New DBDataContext
Try
Dim ProductsQuery = (From pIn dc.Products
Where p.ProductStatus <> "discontinued"
Select New With {.ProductNameValue = p.ProductName,
.ProductNameText = p.ProductName}).OrderBy(Function(lst) lst.ProductNameValue)
For Each r In ProductsQuery
ProductList.Add(New ProductsModel() With {.ProductNameValue = r.ProductNameValue,
.ProductNameText = r.ProductNameText})
Next
Catch ex As Exception
ProductList.Add(New ProductsModel() With {.ProductNameValue = "",
.ProductNameText = ex.Message})
Finally
dc.Connection.Close()
End Try
Return ProductList
End Function
End Class
My problem is that although the muti-select gets populated (with some 5000+ products) the dropdown is not filtering as a user types. For example if I beging typing the word CAKE. As soon as I type C the I-beam disappears and after a second or two the dropdown drops for a brief moment and then disappears clearing the multi-select completely. The only way I can populate at the moment is type the letter A, wait and then scroll through the complete list and select what I need, repeating for each item I need. Have I missed something? Should I introduce paging in order to limit the data?
Thanks

Based on the links provided by Ademar I've changed my code so that I have the following which works....
//products multi-select
// ms datasource
var ms_dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "Home/Products",
type: "GET",
dataType: "json"
}
},
schema: {
model: {
fields: {
"ProductName": {
type: "string"
}
}
}
}
});
// ms widget options
var ms_options = {
autoBind: false,
minLength: 4,
maxSelectedItems: 25,
dataTextField: "ProductName",
dataValueField: "ProductName",
filter: "contains",
placeholder: "Select Product(s)",
dataSource: ms_dataSource
};
// create ms widget
$("#msProducts").kendoMultiSelect(ms_options);
I have also amended my Product Class so that it give just a list of product names that I use as both the tag text and value in the multiselect.

Related

Update the Kendo UI page when kendoAutoComplete is selected

I've added in a kendoAutoComplete widget to a template Kendo UI. The widget is linked to the employee names from employees-list.json and suggesting names correctly.
<p>Search Member: <input id="member-auto-complete" /></p>
<script>
$('#member-auto-complete').kendoAutoComplete({
dataTextField: "EmployeeName",
dataSource: {
transport: {
read: {
url: './content/employees-list.json',
crossDomain: true,
dataType: "jsonp",
jsonp: false,
jsonpCallback: "callback_el",
}
},
},
change: onCriteriaChange,
});
</script>
I'm now unsure how to make the page update when a suggested name is clicked on, the way that it does when you just click on the employee from the side list menu.
I think it is related to the employee variable not updating in the onCriteriaChange function
function onCriteriaChange() {
var employeeList = $("#employees-list").data("kendoListView"),
employee = employeeList.dataSource.getByUid(employeeList.select().attr("data-uid")),
employeeQuarterSales = $("#employee-quarter-sales").data("kendoChart"),
employeeAverageSales = $("#employee-average-sales").data("kendoChart"),
teamSales = $("#team-sales").data("kendoChart"),
employeeSales = $("#employee-sales").data("kendoScheduler"),
startDate = $("#start-date").data("kendoDatePicker"),
endDate = $("#end-date").data("kendoDatePicker"),
filter = {
EmployeeID: employee.EmployeeID,
startDate: kendo.format("{0:MM/dd/yyyy hh:mm:ss}", startDate.value()),
endDate: kendo.format("{0:MM/dd/yyyy hh:mm:ss}", endDate.value())
},
template = kendo.template($("#employeeBioTemplate").html());
console.log(employee)
$("#employeeBio").html(template(employee));
employeeSales.dataSource.filter({
field: "EmployeeID",
operator: "eq",
value: employee.EmployeeID
});
teamSales.dataSource.read(filter);
employeeQuarterSales.dataSource.read(filter);
employeeAverageSales.dataSource.read(filter);
}
Here's the github repo
https://github.com/frankli-n/Kendo-UI-for-jQuery/blob/main/apptemplates/dashboard/index.html

Dynamic search bar - Adding element from drop down in ASP.NET MVC5

I'm programming in ASP.NET MVC5. On one of my views I need to be able to create a search bar. For this example, lets say you are searching for names. When you start typing a person's name, all of the results will be displayed in a drop down list as you type.
Here is the tricky part that I need help with. I want there to be a button for each entry in the drop down list to "Add" that person name to a table.
For example, I'm looking for the name "Debo" As I type "D-E-B", I see the name I want in the drop down list. I click "Add" and it removes the name "Debo" from the drop down list and adds it to my table. Once "Debo" has been added to the table, I need to be able to see Debo's age and gender that I wouldn't see in the drop down list.
I don't have any code examples because I'm not even sure where to start. I've researched this like crazy, but I cannot find anything. Any help or pointing me in the right direction, will be greatly appreciated,
I am using autocomplete by JQueryUI.
Please refer below code hopefully it will helps you.
JavaScript Code:
$("#member_CompanyName").autocomplete({
highlightClass: "bold-text",
search: function () {
$(this).addClass('working');
},
source: function (request, response) {
var companyDetails = new Array();
$.ajax({
url: "/ControllerName/JsonActionResult",
async: false,
data: {
"parm": request.term
},
success: function (data) {
if (data.length === 0) {
companyDetails[0] = {
label: "No Result Found",
Id: ""
};
} else {
for (var i = 0; i < data.length; i++) {
companyDetails[i] = {
label: data[i].Value,
Id: data[i].Key
};
$("#no-companyfound").css("display", "none");
}
}
}
});
response(companyDetails);
},
minLength: 2,
select: function (event, ui) {
/*Select Function works on when you selects element from Response List*/
$.ajax({
async: false,
url: "/ControllerName/JsonActionResultonClick",
data: {
"id": ui.item.Id
},
success: function (data) {
// Do your success logic here
},
error: function (xhr, ajaxOptions, thrownError) {
// Error Logic here
}
});
},
open: function () {
$(this).removeClass("ui-corner-all").addClass("ui-corner-top");
},
close: function () {
$(this).removeClass("ui-corner-top").addClass("ui-corner-all");
}
});
Controller Code:
[HttpGet]
public JsonResult JsonActionResult(string parm) {
// Replace your special Character like "-,~" etc from your search string
var result = new List < KeyValuePair < string,
string >> ();
foreach(var item in _obj_fulldetails.GetCompanylistSearch(parm)) {
result.Add(new KeyValuePair < string, string > (item.Value.ToString(), item.Text));
}
return Json(result, JsonRequestBehavior.AllowGet);
}
You can implement "Add"
button your logic on Item select. If you still want add button you can edit response string into JS.
See my response screenshot :

load jqGrid on button click but it fails on second time

I'm using jqGrid to display data from database. There are 2 textboxes to input the criteria. After inputting the criteria and clicking the Show button, jqGrid is shown to the page.
The second time I clicked the Show button with a different set of criteria entered nothing happens. It still shows data from the first click. How do I solve this?
View:
#section styles {
<link href="~/Content/themes/redmond/jquery-ui.css" rel="stylesheet" />
<link href="~/Content/jquery.jqGrid/ui.jqgrid.css" rel="stylesheet" />
}
<h2>Index</h2>
<p class="form-inline">
Ext: <input type="text" class="form-control" id="extUsed" />
Date: <input type="text" class="form-control" id="startOfCall" readonly="readonly" />
<button class="btn btn-primary" id="btnShow">Show</button>
</p>
<table id="grid"></table>
<div id="pager"></div>
#section scripts {
<script src="~/Scripts/i18n/grid.locale-en.js"></script>
<script src="~/Scripts/jquery.jqGrid.min.js"></script>
<script>
var firstClick = true;
$(function () {
$("#startOfCall").datepicker();
$("#btnShow").click(function (e) {
e.preventDefault();
if (!firstClick) {
$("#grid").trigger("reloadGrid");
} else {
$("#grid").jqGrid({
mtype: "GET",
url: "#Url.Content("~/CallTransaction/GetCallTransactionList")",
datatype: "json",
colNames: ["Ext Used", "Start of Call", "Destination Number"],
colModel: [
{ name: "ExtUsed", index: "ExtUsed" },
{ name: "StartOfCall", index: "StartOfCall", formatter: "date", formatoptions: { srcformat: 'd/m/Y', newformat: 'd/m/Y' } },
{ name: "DestinationNumber", index: "DestinationNumber" }
],
postData: {
"CallTransaction.ExtUsed": $("#extUsed").val(),
"CallTransaction.StartOfCall": $("#startOfCall").val()
},
pager: jQuery("#pager"),
rowNum: 10,
rowList: [10, 25, 50],
height: "100%",
caption: "Call Transaction",
autowidth: true,
//sortname: "ExtUsed",
sortable: true,
viewrecords: true,
emptyrecords: "No records to display",
});
$("#grid").jqGrid('navGrid', '#pager', { edit: false, add: false, del: false, search: false });
}
firstClick = false;
});
});
</script>
}
Controller:
public JsonResult GetCallTransactionList(CallTransaction callTransaction, string sidx, string sord, int page, int rows)
{
int pageIndex = page - 1;
int pageSize = rows;
var callTransactionResult = db.Search(callTransaction);
int totalRecords = callTransactionResult.Count();
var totalPages = (int)Math.Ceiling((float)totalRecords / (float)rows);
if (sord.ToUpper() == "DESC")
{
callTransactionResult = callTransactionResult.OrderByDescending(ct => ct.ExtUsed).ToList();
callTransactionResult = callTransactionResult.Skip(pageIndex * pageSize).Take(pageSize).ToList();
}
else
{
callTransactionResult = callTransactionResult.OrderBy(ct => ct.ExtUsed).ToList();
callTransactionResult = callTransactionResult.Skip(pageIndex * pageSize).Take(pageSize).ToList();
}
var jsonData = new
{
total = totalPages,
page,
records = totalRecords,
rows = callTransactionResult
};
return Json(jsonData, JsonRequestBehavior.AllowGet);
}
It's important to understand that the current code set one value of postData during creating the grid. The value of postData parameter will be object with properties evaluated at the moment of creating of the grid.
To fix the code you need use function as the value of postData properties:
postData: {
"CallTransaction.ExtUsed": function () { return $("#extUsed").val(); },
"CallTransaction.StartOfCall": function () { return $("#startOfCall").val(); }
}
See the answer for more details. For understanding: jqGrid uses jQuery.ajax internally and jQuery.ajax uses jQuery.param helper function to process the data parameter (construction using postData) and jQuery.param execute functions if it is the properties of data (postData).
Additionally I would strictly recommend you to use gridview: true option in all your grids (see the answer), add autoencode: true to interpret the input data as the data instead of HTML fragments (it's the default behavior) and to use pager: "#pager" instead of pager: jQuery("#pager").
I recommend you to remove all index properties from colModel and to consider to include additional id property in the data returned from the server with an unique values which come from the database. If some column of the grid already contains the unique value you can add key: true property to the definition of the corresponding column. The reason of such changes is easy to understand if you know that jqGrid have to assign id attribute to every row of grid. The value of id attribute must be unique. The value, used as rowid in the documentation, will be used in the most callbacks of jqGrid to identify the row. The same value will be send to the server if you will implement editing of data later. If you don't specify any rowid in the input data jqGrid have to assign some other value to id. The default value will be 1,2,3... On the other side if you load the data from the database you have native ids of the rows. The usage of the native ids can "simplify your live" in the future.

Extending kendo multiselect and working with MVVM

I'm trying to extend a kendo multiselect so that it has a default data source as well as templates. It's all working except the pre-loaded values in the MVVM object. When I start updating the exented multiselect, the value of the MVVM gets updated, the initial items are just not pre-loaded:
kendo.ui.plugin(kendo.ui.MultiSelect.extend({
init: function(element, options) {
var ds = new kendo.data.DataSource({
type: "json",
serverFiltering: true,
transport: {
read: {
url: "/SecurityEntities",
dataType: "json"
},
parameterMap: function(data) {
return {
prefixText: '',
count: 5,
getUsers: true,
getGroups: false
};
}
},
schema: {
data: function(data) {
console.log($.parseJSON(data));
return $.parseJSON(data);
}
}
});
options = options == null ? {} : options;
options.itemTemplate = "...";
options.tagTemplate = "...";
options.dataSource = ds;
kendo.ui.MultiSelect.fn.init.call(this, element, options);
},
options: {
name: 'EntityMultiSelect'
}
}));
kendo.data.binders.widget.entitymultiselect =
kendo.data.binders.widget.multiselect;
Then my html is:
<div data-bind="value: machine.Managers" data-role="entitymultiselect"
data-delay="400" data-animation="false"
data-placeholder="Select users to notify"></div>
And I am binding the whole container to the page's viewModel object.
I've seen other people have issues with this very problem and added the
kendo.data.binders.widget.entitymultiselect =
kendo.data.binders.widget.multiselect;
(And yes that does seem like a bug)
But it still doesn't work.
When there are already values in Machine.Managers, it doesn't load them. However, if I add values to the multiselect, they get added to Machine.Managers .
EDIT:
I've added a live example
At least in your demo it's a trivial problem: your data-value-field is wrong. As a result, the binder can't match the selected elements.
Instead of
<div data-role="entitymultiselect"
data-bind="value: selected"
data-value-field="ProductId"></div>
you need
<div data-role="entitymultiselect"
data-bind="value: selected"
data-value-field="ProductID"></div>
(working demo)
Since you're not defining the value field in the code in your question, it might be the same issue.

How do I create a delete button on every row in slickgrid with confirmation?

As the title said it, how do I do it?, I am using this button created by jiri:
How do i create a delete button on every row using the SlickGrid plugin?
when I add an if(confirmation(msg)) inside the function it repeats me the msg ALOT
maybe its because i refresh-ajax the table with each modification.
ask me if you need more info, I am still noob here in stackoverflow :P
(also if there is someway to "kill" the function)
here is the button, iam using(link) i added the idBorrada to check whetever the id was already deleted and dont try to delete it twice, also here is a confirm, but when i touch cancel it asks me again.
$('.del').live('click', function(){
var me = $(this), id = me.attr('id');
//assuming you have used a dataView to create your grid
//also assuming that its variable name is called 'dataView'
//use the following code to get the item to be deleted from it
if(idBorrada != id && confirm("¿Seguro desea eleminarlo?")){
dataView.deleteItem(id);
Wicket.Ajax.ajax({"u":"${url}","c":"${gridId}","ep":{'borrar':JSON.stringify(id, null, 2)}});
//This is possible because in the formatter we have assigned the row id itself as the button id;
//now assuming your grid is called 'grid'
//TODO
grid.invalidate();
idBorrada= id;
}
else{
};
});
and i call the entire function again.
hope that help, sorry for the grammar its not my native language
Follow these steps,
Add a delete link for each row with of the columns object as follows,
var columns =
{ id: "Type", name: "Application Type", field: "ApplicationType", width: 100, cssClass: "cell-title", editor: Slick.Editors.Text, validator: requiredFieldValidator, sortable: true },
{ id: "delete", name: "Action", width: 40, cssClass: "cell-title", formatter: Slick.Formatters.Link }
];
Add a Link Formatter inside slick.formatters.js as follows,
"Formatters": {
"PercentComplete": PercentCompleteFormatter,
"YesNo": YesNoFormatter,
"Link": LinkFormatter
}
function LinkFormatter(row, cell, value, columnDef, dataContext) {
return "<a style='color:#4996D0; text-decoration:none;cursor:pointer' onclick='DeleteData(" + dataContext.Id + ", " + row + ")'>Delete</a>";
}
Add the following delete function in javascript
function DeleteData(id, rowId) {
var result = confirm("Are you sure you want to permenantly delete this record!");
if (result == true) {
if (id) {
$.ajax({
type: "POST",
url: "DeleteURL",
data: { id: id },
dataType: "text",
success: function () {
},
error: function () {
}
});
}
dataView.deleteItem(id);
dataView.refresh();}
}

Categories

Resources