I am using jEditable and am wondering if if it is possible to have a select (type=select) with optgroups?
I have managed to do this by creating a custom input type (I called it optgroup).
It works on the assumption the json for data is in the form;
var json = [{"Foo":[{"id":1,"name":"aaa"},{"id":2,"name":"bbb"}]},{"Bar":[{"id":3,"name":"ccc"},{"id":4,"name":"ddd"}]}];
This is the code;
optgroup: {
element : function(settings, original) {
var select = $('<select class="opt" />');
$(this).append(select);
return(select);
},
content : function(data, settings, original) {
if (String == data.constructor) {
eval ('var json = ' + data);
} else {
var json = data;
}
var addto = $('select', this);
$.each(json, function(i, optgroups) {
$.each(optgroups, function(groupName, options) {
var $optgroup = $("<optgroup>", {label: groupName});
$optgroup.appendTo(addto);
$.each(options, function(j, option) {
var $option = $("<option>", {text: option.name, value: option.id});
$option.appendTo($optgroup);
});
});
});
}
}
To use;
$('.editable').find('td').editable(
function(v, s) {
// do whatevere you need to...
},
{
"data" : [{"Foo":[{"id":1,"name":"aaa"},{"id":2,"name":"bbb"}]},{"Bar":[{"id":3,"name":"ccc"},{"id":4,"name":"ddd"}]}],
"indicator": 'Saving ...',
"tooltip": 'Double Click to edit',
"type": 'optgroup',
"submit": 'Save changes',
"event": 'dblclick'
}
);
You have to add
optgroup: {
element: function (settings, original) {
var select = $('<select />');
$(this).append(select);
return (select);
},
content: function (data, settings, original) {
if (String == data.constructor) {
eval('var json = ' + data);
} else {
var json = data;
}
var addto = $('select', this);
$.each(json, function (i, optgroups) {
$.each(optgroups, function (groupName, options) {
var $optgroup = $("<optgroup>", {
label: groupName
});
$optgroup.appendTo(addto);
$.each(options, function (j, option) {
var $option = $("<option>", {
text: option.name,
value: option.id
});
if (option.selected !== null && option.selected !== undefined && option.selected) {
$option.attr('selected', 'selected');
}
$option.appendTo($optgroup);
});
});
});
}
}
into your jquery.jeditable.js, find "types" and paste into that array. After that you file should look like:
types: {
textarea:...,
select:...
number:...
...
optgroup:...
}
Next you have to use it.
$("#yourControlSelect").editable("/controllerName/ActionToExecute", {
data: #Html.Action("JEditbaleOptGroup", "ControllerName"),
type: 'optgroup', //Same as you created before
...
});
Remember the format of data, it has to be:
[
{"Category1": [{"id": 1,"name": "Product1"}, {"id": 2,"name": "Product2"}]},
{"Category2": [{"id": 3,"name": "Product3"}, {"id": 4,"name": "Product4"}]},
{"Category3": [{"id": 5,"name": "Product5"}, {"id": 6,"name": "Product6"}]}
]
Finally, here's the model to create and return it
public class JEditable
{
public string Id { get; set; }
public string Descripcion { get; set; }
}
public class JEditableOptGroup
{
public string Nombre { get; set; }
public IEnumerable<JEditable> Hijos { get; set; }
}
Fill the model
var grupos = Repositorio.SelectListOfYourDataType(x => true).GroupBy(x => x.ColToGrouping);
foreach (var grupo in grupos)
{
List<JEditable> hijos = new List<JEditable>();
foreach (var item in grupo.OrderBy(x=>x.nombre_g5))
hijos.Add(new JEditable() { Id = item.Id_g5, Descripcion = item.nombre_g5.Trim() + " (" + item.Balance_g5 + ") " + item.cuenta_g5.Trim() });
jEditable.Add(new JEditableOptGroup() { Nombre = grupo.Key + " " + grupo.FirstOrDefault().cuenta_g4.Trim(), Hijos = hijos });
}
return Funciones.JEditableDropDownList(jEditable);
Tranform data to the correct format:
internal static string JEditableDropDownList(List<JEditableOptGroup> grupos)
{
StringBuilder sb = new StringBuilder();
sb.Append("[");
foreach (var grupo in grupos)
{
StringBuilder hijos = new StringBuilder();
foreach (var item in grupo.Hijos)
hijos.Append("{" + string.Format("id:'{0}',name:'{1}'", item.Id, item.Descripcion) + "},");
sb.Append("{" + string.Format("'{0}':[{1}]", grupo.Nombre, hijos) + "},");
}
sb.Append("]");
return sb.ToString();
}
Enjoy it!
Related
How to create dynamic JSON as per input. Filter data and create appropriate JSON objects key and values pairs
Below is the database.
Below is the code which had tried but won't work...
success: function (data) {
//lenght
data.value.length
// console.log(data);
//HC list JSON
empData = '[';
$.each(data.value, function (index, item) {
var dataLen = data.value.length;
empData += `{`
if (item.STATUS == 'Active') {
if (item.NODE == 'Testing') {
empData += `"DDM_CO2" : {
"DESIGNATION": "${item.DESIGNATION}",
"EMPLOYMENT": "${item.EMPLOYMENT}",
"GENDER": "${item.GENDER}",
"Name1": "${item.Name1}",
"ROLE": "${item.ROLE}"
},`
} else if (item.NODE == 'Devlopment') {
empData += `"GPH" : {
"DESIGNATION": "${item.DESIGNATION}",
"EMPLOYMENT": "${item.EMPLOYMENT}",
"GENDER": "${item.GENDER}",
"Name1": "${item.Name1}",
"ROLE": "${item.ROLE}"
}`
}
}
});
empData += ']';
empData = JSON.parse(empData);
console.log(empData);
//HC list JSON END
},
Something like this should work
function (data) {
//create array to store emp objects
var empData = new Array();
$.each(data.value, function (index, item) {
if (item.STATUS == 'Active') {
if (item.NODE == 'Testing') {
//create custom object
var emp = {
DDM_CO2: {
DESIGNATION: item.DESIGNATION,
EMPLOYMENT: item.EMPLOYMENT
//etc: item.etc
//etc: item.etc
//etc: item.etc
}
};
//add to array
empData.push(emp);
} else if (item.NODE == 'Devlopment') {
var emp = {
GPH: {
DESIGNATION: item.DESIGNATION,
EMPLOYMENT: item.EMPLOYMENT,
GENDER: item.GENDER,
Name1: item.Name1,
ROLE: item.ROLE
}
};
empData.push(emp);
}
}
}
All I am trying to do is that I want to refresh my DataTable when the page is relaoded/refreshed. Right now on refreshing the page it retains its data. My application is using ASP.Net MVC tech.
Here is my Data Table and relevant functions:
$(document).ready(function () {
//debugger;
var table = $('#user_session_center_grid').DataTable({
"searching": false,
"colReorder": true,
"lengthChange": false,
"processing": true,
"serverSide": true,
"autoWidth": false,
"ajax": {
cache: false,
url: "#Url.Action("GetUserSessionHistory", "LoggedIn")",
type: 'POST',
data: function (data) {
data.SortBy = 'Month';
data.FromDate = "";
data.ToDate = "";
data.userSearch = $('#userSearch').val();
if (event) {
var objDtFilter = event.target;
if ($(objDtFilter).hasClass('dtFilter')) {
data.FromDate = event.target.getAttribute('fromdt');
data.ToDate = event.target.getAttribute('todt');
}
if ($(objDtFilter).hasClass('dtSort'))
data.SortBy = event.target.getAttribute('sort');
if ($(objDtFilter).hasClass('UserTypeFilter'))
data.value1 = event.target.getAttribute('value');
console.log(data.value1);
}
},
},
"language": {
oPaginate: {
sNext: '<i class="fa fa-chevron-right"></i>',
sPrevious: '<i class="fa fa-chevron-left"></i>',
sFirst: '<i class="fa fa-chevron-right"></i>',
sLast: '<i class="fa fa fa-chevron-left"></i>'
}
},
"columns": [
{
data: null,
class: "userName",
render: function (data, type, row) {
return "<div>" + data.FirstName + " " + data.LastName + "</div></td>";
}
},
{
data: null,
class: "startDate",
render: function (data, type, row) {
var parsedDate = JSON.parse(JSON.stringify(data.StartTime), ToJavaScriptDate);
return "<div>" + parsedDate + "</div></td>";
}
},
//{ 'data': 'User_ID' },
//{ 'data': 'FirstName' },
//{ 'data': 'LastName' },
//{ 'data': 'StartTime' },
],
});
table.on('draw', function () {
var widthofPagination = $('.dataTables_paginate.paging_simple_numbers').width() + 25;
$('#user_session_center_grid_info').css({ width: 'calc(100% - ' + widthofPagination + 'px)' });
});
$("#date_filter_ul.dropdown-menu li a").click(function () {
//debugger;
$('#date_filter_ul').removeClass('show');
$(this).closest('#CategoryFilter').find('.csp-select > span').text("Duration:" + $(this).text());
$('#user_session_center_grid').DataTable().ajax.reload();
});
$("#user_session_center_status_ul.dropdown-menu li a").click(function () {
$('#user_session_center_status_ul').removeClass('open');
$(this).closest('#StatusFilter').find('.csp-select > span').text($(this).text());
$('#user_session_center_grid').DataTable().ajax.reload();
});
});
Here are my controller functions:
public ActionResult UserSessionCenter()
{
if (Session["selectedCustomer"] == null)
{
Session["selectedCustomer"] = 9;
}
int customerId = (int)Session["selectedCustomer"];
var model = new UserSessionHistory();
var daccess = new ApplicationCommon.Ado.SqlDataAccess();
var customerNamesDt = daccess.GetUserNames(customerId);
var customerList = new List<UserSessionData>();
for (var i = 0; i < customerNamesDt.Rows.Count; i++)
{
var userinfo = new UserSessionData();
userinfo.CustomerId = customerNamesDt?.Rows[i]["Customer_Id"].ToString() ?? "";
userinfo.CustomerName = customerNamesDt?.Rows[i]["Customer_Name"].ToString() ?? "";
userinfo.UserId = customerNamesDt?.Rows[i]["User_ID"].ToString() ?? "";
userinfo.UserName = customerNamesDt?.Rows[i]["UserName"].ToString() ?? "";
customerList.Add(userinfo);
}
model.UserInfoList = customerList;
return View(model);
}
[HttpPost]
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public JsonResult GetUserSessionHistory()
{
var draw = Request.Form.GetValues("draw").FirstOrDefault();
var start = Request.Form.GetValues("start").FirstOrDefault();
var length = Request.Form.GetValues("length").FirstOrDefault();
if (Request["value1"] != null)
Session["userId"] = Request["value1"];
int pageSize = length != null ? Convert.ToInt32(length) : 0;
try
{
var UserID = Convert.ToInt32(Session["userId"]);
var filterModel = new FilterSessionHistoryModel();
filterModel.UserID = UserID;
filterModel.Skip = int.Parse(start);
filterModel.Take = int.Parse(length);
var fromDate = Request["FromDate"];
var toDate = Request["ToDate"];
filterModel.userSearch = Request["userSearch"];
if (!string.IsNullOrEmpty(fromDate) && !string.IsNullOrEmpty(toDate))
{
filterModel.DateFrom = fromDate;
filterModel.DateTo = toDate;
}
UserService userService = new UserService();
List<ADM_User_Session_History_Result> SessionList = userService.ADM_User_Session_History(filterModel);
int? numberOfRecords = 0;
if(SessionList.Count>0) {
numberOfRecords=SessionList[0].NumberOfRecords;
}
return Json(new { draw = draw, recordsFiltered = (int)numberOfRecords, recordsTotal = (int)numberOfRecords, data = SessionList }, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
CustomLogging.LogMessage(ex.Message + "/r/n" + ex.Source + "/r/n" + ex.StackTrace, LogType.Error);
return this.GetJSONObject(false, ex.Message.ToString());
}
}
The hierarchy is like this.
1. The Admin user can use any customer
2. One customer can have many users
3. The table shows the time of log in of the user selected.
The problem is that the list through which the Admin can change the Customer is in the top nav present in _Layout.cshtml where as this data table is in another view. The data changes fine while cahanging the user but I need it to reload or get empty when the customer is changed.
old browsers like 'explorer' keep caching the info from a first ajax call,
you can try to set the cash flag to false and the table will be updated each time
function ReLoadTable() {
$.ajax({
cache: false,
url: 'Your URL',
type: 'POST',
in controller put this attribute
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class HomeController : Controller
{
finally in your Global.asax file add this function
protected void Application_PreSendRequestHeaders(Object sender, EventArgs e)
{
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetAllowResponseInBrowserHistory(false);
}
I'm using select2 JQuery plugin to implement an autocomplete input-like element backed by a json endpoint, in this select2 input, I want the user can also create new objects into the same element by just giving them names or using the available on the endpoint.
My problem is that I need to access the processed 'data' mapping generated on 'processResults' key outside its function, actually inside the createTag function, I'm not sure if I need to use some JQuery method to access the result or control it using some global variable.
Here is my code:
HTML:
<p>
<select class="js-example-tags form-control" multiple="multiple"></select>
</p>
JS:
var $tags = $(".js-example-tags");
var responsejson;
$.fn.select2.amd.require(['select2/compat/matcher'], function(oldMatcher) {
$tags.select2({
ajax: {
data: function(params) {
var unicode = "\uf8ff";
var startAt = '"' + params.term + '"';
var endAt = '"' + params.term + unicode + '"';
var query = {
orderBy: "\"lowerCaseName\"",
startAt: startAt.toLowerCase(),
endAt: endAt.toLowerCase(),
print: "\"pretty\""
};
// Query paramters will be ?search=[term]&page=[page]
return query;
},
url: 'https://someappname.firebaseio.com/substancies.json?',
processResults: function(data, key) {
return {
results: $.map(data, function(obj, key) {
responsejson = {
id: key,
lower: obj.lowerCaseName,
text: obj.commonName
};
return responsejson;
})
};
}
},
tags: true,
createTag: function(params) {
if (responsejson !== undefined) {
console.log("Oppa");
}
var term = $.trim(params.term);
if (term === "") {
return null;
}
var optionsMatch = false;
var arrValue = $(".js-example-tags").select2('data');
for (var i = 0; i < arrValue.length; i++) {
var var1 = arrValue[i].lower;
var var2 = term.toLowerCase();
if (term.toLowerCase() === arrValue[i].lower) {
optionsMatch = true;
break;
}
}
if (optionsMatch) {
return null;
}
return {
id: -1,
text: term
};
},
minimumInputLength: 3,
tokenSeparators: [','],
casesensitive: false
});
});
I m trying to call web method from jsTree but unable to call it. can someone please help me out to get this resolved.
my jsTree function is:-
$('#tree').jstree({
"json_data": {
"ajax": {
"type": "POST",
"dataType": "json",
"async": true,
"contentType": "application/json;",
"opts": {
"method": "POST",
"url": "../../SurveyReport/Metrics.aspx/GetAllNodes11"
},
"url": "../../SurveyReport/Metrics.aspx/GetAllNodes11",
"data": function (node) {
if (node == -1) {
return '{ "operation" : "get_children", "id" : -1 }';
}
else {
//get the children for this node
return '{ "operation" : "get_children", "id" : ' + $(node).attr("id") + ' }';
}
},
"success": function (retval) {
alert('Success')
return retval.d;
},
"error": function (r) {
alert(r.attr);
alert('error');
}
}
},
"plugins": ["themes", "json_data"]
});
And web method and data file is:-
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public static List<G_JSTree> GetAllNodes11(string id)
{
if (id != "-1") //-1 means initial load else async loading of children
{
if (id == "10")
//Add 3 children to parent node with id=10.
return AddChildNodes(10, 3, "xxxx");
else
return new List<G_JSTree>();
}
List<G_JSTree> G_JSTreeArray = new List<G_JSTree>();
//Creating the JsTree data
//In live scenarios this will come from db or Web Service
//Add 5 root nodes
G_JSTreeArray.AddRange(AddChildNodes(0, 5, ""));
//Add 4 children to 3rd root node
//The third node has id=30
//The child nodes will have ids like 301,302,303,304
G_JSTreeArray[3].children = (AddChildNodes(30, 4, G_JSTreeArray[3].data)).ToArray();
//Add 5 children to level1 Node at id=302
G_JSTreeArray[3].children[1].children = (AddChildNodes(302, 4, G_JSTreeArray[3].children[1].data)).ToArray();
return G_JSTreeArray;
}
private static List<G_JSTree> AddChildNodes(int _ParentID, int NumOfChildren, string ParentName)
{
List<G_JSTree> G_JSTreeArray = new List<G_JSTree>();
int n = 10;
for (int i = 0; i < NumOfChildren; i++)
{
int CurrChildId = (_ParentID == 0) ? n : ((_ParentID * 10) + i);
G_JSTree _G_JSTree = new G_JSTree();
_G_JSTree.data = (_ParentID == 0) ? "root" + "-Child" + i.ToString() : ParentName + CurrChildId.ToString() + i.ToString();
_G_JSTree.state = "closed"; //For async to work
_G_JSTree.IdServerUse = CurrChildId;
_G_JSTree.children = null;
_G_JSTree.attr = new G_JsTreeAttribute { id = CurrChildId.ToString(), selected = false };
G_JSTreeArray.Add(_G_JSTree);
n = n + 10;
}
return G_JSTreeArray;
}
public class G_JSTree
{
public G_JsTreeAttribute attr;
public G_JSTree[] children;
public string data
{
get;
set;
}
public int IdServerUse
{
get;
set;
}
public string icons
{
get;
set;
}
public string state
{
get;
set;
}
}
public class G_JsTreeAttribute
{
public string id;
public bool selected;
}
}
I want to load the tree in an async fashion from a webmethod in an asp.net page.
Thanks in advance.
I use this Code Successfully By add this Complete Reference :
[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod(ResponseFormat = System.Web.Script.Services.ResponseFormat.Json)] //ResponseFormat.Json)]
public static List<GG_JSTree> GetAllNodes11(string id)
{......}
i trying to autocomplete multiple values in my mvc project , but it autocomplete for first value and second nothing occurred
my view code :
#Html.TextBox("SentUsers", "", new { #class = "text-box"})
#Html.Hidden("UsersId")
java script code :
<script type="text/javascript">
var customData = null;
var userId;
$(function () {
$("#SentUsers")
.bind("keydown", function (event) {
if (event.keyCode === $.ui.keyCode.TAB &&
$(this).data("ui-autocomplete").menu.active) {
event.preventDefault();
}
})
.autocomplete({
minLength: 2,
source: function (request, response) {
$.ajax({
url: "/Ajax/AutoCompleteUsers",
type: "POST",
dataType: "json",
data: { term: request.term },
success: function (data) {
alert(data);
customData = $.map(data, function (item) {
userId = item.UserId;
return { label: item.Name + "(" + item.Email + ")", value: item.Name }
});
response(customData, extractLast(request.term))
}
})
},
focus: function () {
// prevent value inserted on focus
return false;
},
select: function (event, ui) {
var usersIdVal = $("#UsersId").val();
usersIdVal += ", " + userId;
$("#UsersId").val(usersIdVal)
var terms = split(this.value);
// remove the current input
terms.pop();
// add the selected item
terms.push(ui.item.value);
// add placeholder to get the comma-and-space at the end
terms.push("");
this.value = terms.join(", ");
return false;
}
});
});
function split(val) {
return val.split(/,\s*/);
}
function extractLast(term) {
return split(term).pop();
}
controller code :
public JsonResult AutoCompleteUsers(string term)
{
var result = (from r in db.UserItems
where r.Name.ToLower().Contains(term.ToLower())
select new { r.Name, r.Email, r.UserId }).Distinct();
return Json(result, JsonRequestBehavior.AllowGet);
}
when i trying static javascript array the autocomplete multiple values working perfect !
i think error may be in this block , but i dont know the solution
customData = $.map(data, function (item) {
userId = item.UserId;
return { label: item.Name + "(" + item.Email + ")", value: item.Name }
});
Thanks every body who tried to solve my question , and who isnt, i solved my question, and here is the solution for everybody:
my view code :
#Html.TextBox("SentUsers", "", new { #class = "text-box"})
#Html.Hidden("UsersId")
my javascript code :
<script type="text/javascript">
$(function () {
$("#SentUsers")
.bind("keydown", function (event) {
if (event.keyCode === $.ui.keyCode.TAB &&
$(this).data("ui-autocomplete").menu.active) {
event.preventDefault();
}
})
.autocomplete({
minLength: 2,
source: function( request, response ) {
$.getJSON("/Ajax/AutoCompleteUsers", {
term: extractLast( request.term )
}, response );
},
search: function () {
// custom minLength
var term = extractLast(this.value);
if (term.length < 2) {
return false;
}
},
focus: function () {
// prevent value inserted on focus
return false;
},
select: function (event, ui) {
var usersIdVal = $("#UsersId").val();
usersIdVal += ", " + ui.item.userId;
$("#UsersId").val(usersIdVal)
var terms = split(this.value);
// remove the current input
terms.pop();
// add the selected item
terms.push(ui.item.value);
// add placeholder to get the comma-and-space at the end
terms.push("");
this.value = terms.join(", ");
return false;
}
});
});
function split(val) {
return val.split(/,\s*/);
}
function extractLast(term) {
return split(term).pop();
}
my controller code :
public JsonResult AutoCompleteUsers(string term)
{
var result = (from r in db.UserItems
where r.Name.ToLower().Contains(term.ToLower())
select new { label = r.Name + "(" + r.Email + ")", value = r.Name, userId = r.UserId }).Distinct();
return Json(result, JsonRequestBehavior.AllowGet);
}