In an ASP .NET MVC Razor view, I have a dropdown list as follows:
#Html.DropDownListFor(model => model.SelectedDeviceModel, Model.DeviceModelList)
DeviceModelList is just a SelectList.
How can I dynamically fill the DeviceModelList depending on a client side action like a button click or another drop down selection using Javascript/jQuery/Ajax?
You could externalize this dropdown into a partial:
#model MyViewModel
#Html.DropDownListFor(model => model.SelectedDeviceModel, Model.DeviceModelList)
then in your main view include it inside some container:
#model MyViewModel
...
<div id="ddlcontainer">
#Html.Partial("Foo", Model)
</div>
...
then you could have a controller action which takes some parameter and based on its value it renders this partial:
public ActionResult Foo(string someValue)
{
MyViewModel model = ... go ahead and fill your view model
return PartialView(model);
}
Now the last part is to send the AJAX request to refresh the drop down list when some event occurs. For example when the value of some other ddl changes (or something else, a button click or whatever):
$(function() {
$('#SomeOtherDdlId').change(function() {
// when the selection of some other drop down changes
// get the new value
var value = $(this).val();
// and send it as AJAX request to the newly created action
$.ajax({
url: '#Url.Action("foo")',
type: 'POST',
data: { someValue: value },
success: function(result) {
// when the AJAX succeeds refresh the ddl container with
// the partial HTML returned by the Foo controller action
$('#ddlcontainer').html(result);
}
});
});
});
Another possibility consists into using JSON. Your Foo controller action would only return some Json object containing the new key/value collection and in the success callback of the AJAX request you would refresh the drop down list. In this case you don't need to externalize it into a separate partial. For example:
$(function() {
$('#SomeOtherDdlId').change(function() {
// when the selection of some other drop down changes
// get the new value
var value = $(this).val();
// and send it as AJAX request to the newly created action
$.ajax({
url: '#Url.Action("foo")',
type: 'POST',
data: { someValue: value },
success: function(result) {
// when the AJAX succeeds refresh the dropdown list with
// the JSON values returned from the controller action
var selectedDeviceModel = $('#SelectedDeviceModel');
selectedDeviceModel.empty();
$.each(result, function(index, item) {
selectedDeviceModel.append(
$('<option/>', {
value: item.value,
text: item.text
})
);
});
}
});
});
});
and finally your Foo controller action will return Json:
public ActionResult Foo(string someValue)
{
return Json(new[] {
new { value = '1', text = 'text 1' },
new { value = '2', text = 'text 2' },
new { value = '3', text = 'text 3' }
});
}
For a similar example you may take a look at the following answer.
Related
I created two new buttons in JS and replaced the original Add button in tree view of a model:
ListView.include({
render_buttons: function() {
var self = this;
this._super.apply(this, arguments)
if (this.model=='account.cash'){
if (this.$buttons) {
this.$buttons.find('.o_list_button_income').on('click', this.proxy('do_new_income'))
this.$buttons.find('.o_list_button_add').css({"display":"none"})
}
}
},
do_new_income: function () {
var model = new Model('account.cash');
var self = this;
model.call('new_income', [[]])
With this button I´m trying to call a form view by following method:
#api.model
def new_income(self):
view_id = self.env.ref('account.view_cash_statement_form').id
context = self._context.copy()
return {
'name': 'New income',
'view_type': 'form',
'view_mode': 'form',
'views': [(view_id, 'form')],
'res_model': 'account.cash',
'context': context,
'target': 'current',
'type': 'ir.actions.act_window'
}
However this is not working. When I try to call this method as a test in other view from button defined in standard XML view definition, it is behaving as expected.
model.call('new_income', [[]]).then(function (res) { self.do_action(res)})
where res is the returned value from python did the trick
I don't want select2 multi select drop down loose data in page refresh. select2 drop down should maintain state
below is my code. its working fine, I have only problem that select2 is losing selection/data if we refresh the page.My requirement is even after page refresh it should not remove there values/or empty.
$processOrderNbr.select2({
ajax: getProcessOrderNbr(),
minimumInputLength: 4,
placeholder: " ",
allowClear: false,
multiple: true
});
function getProcessOrderNbr() {
return {
url: 'GetProcessOrder',
dataType: 'json',
delay: 250,
data: function (params) {
return {
searchKeyword: params
};
},
results: function (data) {
return {
results: $.map(data, function (item) {
return {
text: item,
id: item
}
})
};
}
};
}
You need to put them again into the select2 boxes.
I had a similar issue, where I work with window.sessionStorage to store the selected values. After reloading the page, I set the values stored in the session storage into the select2 boxes with this code:
var selectionList = [{ id: window.sessionStorage.getItem("searchValue"), text: window.sessionStorage.getItem("searchValue")}];
$("#searchValue").select2({
data: selectionList
});
$('#searchValue').val(window.sessionStorage.getItem("searchValue")).trigger("change");
To store the values in the window.sessionStorage you can use this code:
$('#searchValue').select2({
...
.on("change", function (e) {
window.sessionStorage.setItem("searchValue", $(this).val());
}
...
Maybe this solution helps you in your case, but someone knows a better solution?
If you need to show the previous wrote value after reloading the page without losing the data that is the solution.
var dataCategory = JSON.parse(sessionStorage.getItem('category'));
var select = $("#category");
select.select2({
tags: true,
allowClear: true,
maximumInputLength: 30,
maximumSelectionLength: 20,
tokenSeparators: [',', ' '],
data: dataCategory
}).on("change", function (e) {
var selected = []; // create an array to hold all currently wrote by user
// loop through each option
$('#category option').each(function() {
// if it's selected, add it to the array above
if (this.selected) {
selected.push(this.value);
}
});
// store the array of selected options
sessionStorage.setItem('category', JSON.stringify(selected));
});
// set and show the previous wrote keywords
var dataCategoryLength = dataCategory.length;
for (var i =0; i < dataCategoryLength; i++) {
$('#category').val(dataCategory).trigger('change');
}
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 :
I implemented a tagging system where you can choose from existing tags or add new tags. After a new tag has been selected it will persisted using an AJAX call.
For achieving this I use the callback createTag and the event select2:select. Because I like to create the tag only when it is selected I do an AJAX call for this if the event select2:select gets triggered.
The problem is that I need to update the already created option of select2 with the ID I get from persisting my new tag to the database. What's the cleanest solution for this?
Here's what I have:
$('select.tags').select2({
tags: true,
ajax: {
url: '{{ path('tag_auto_complete') }}',
processResults: function (data) {
return {
results: data.items,
pagination: {
more: false
}
};
}
},
createTag: function (tag) {
return {
id: tag.term, // <-- this one should get exchanged after persisting the new tag
text: tag.term,
tag: true
};
}
}).on('select2:select', function (evt) {
if(evt.params.data.tag == false) {
return;
}
$.post('{{ path('tag_crrate_auto_complete') }}', { name: evt.params.data.text }, function( data ) {
// ----> Here I need to update the option created in "createTag" with the ID
option_to_update.value = data.id;
}, "json");
});
My problem was that I did not add the new tag as an <option> tag to the native select field.
This is necessary because select2 checks for the values set trough select2.val(values) if an <option> tag with this value does exist. If not select2 silently throws the value out of the array and sets the array of values which have a corresponding option tag in the underlying select field.
So this is how it works correct now (for select2 4.0.x):
$('select.tags').select2({
tags: true,
ajax: {
url: '{{ path('tag_auto_complete') }}',
processResults: function (data) {
return {
results: data.items,
pagination: {
more: false
}
};
}
},
createTag: function (tag) {
return {
id: tag.term,
text: tag.term,
tag: true
};
}
}).on('select2:select', function (evt) {
if(evt.params.data.tag == false) {
return;
}
var select2Element = $(this);
$.post('{{ path('tag_crrate_auto_complete') }}', { name: evt.params.data.text }, function( data ) {
// Add HTML option to select field
$('<option value="' + data.id + '">' + data.text + '</option>').appendTo(select2Element);
// Replace the tag name in the current selection with the new persisted ID
var selection = select2Element.val();
var index = selection.indexOf(data.text);
if (index !== -1) {
selection[index] = data.id.toString();
}
select2Element.val(selection).trigger('change');
}, 'json');
});
The minimal AJAX response (JSON format) has to look like this:
[
{'id': '1', 'text': 'foo'},
{'id': '2', 'text': 'bar'},
{'id': '3', 'text': 'baz'}
]
You may add additional data to each result for let's say own rendering of the result list with additional data in it.
Just to update:
The new syntax is
e.params.args.data.id
not
e.params.data.id
My problem is that I Have Hierarchical grid (Master and Child) let say I Have a Department Grid it contains List of Employee Grid, and they both use same datasource.
Here's my GridChild Code:
function detailInit (e){
var msterRow = e.sender.items().index(e.masterRow).toString();
var grid = $("<div id='childGrid"+msterRow+"'
class=childGrid'/>").appendTo(e.detailCell).kendoGrid({
data: e.data.DeptEmployees,
schema: {
model: { fields: { foo: {--skip--}, bar: {--skip--} } }
},
toolbar: ["create", "cancel", "save"],
editable: "popup",
columns: [ --skip--]
save: function(e){
ajaxUpdateDepartment(msterRow, this.dataSource.data());
}
})
As you can see i use data: e.data.DeptEmployees, as child data source to fetch data.
Now I'm stacked in how can I update the child data source?
What I have Tried:
I add child's dataSource.transport for updates, but my child grid keeps on loading.
So I end up configuring the save: function (e) and simply send all data source of the current child but popup editor didn't close at all. And I'm having difficulty to refresh the child data source.
I also attempt to convert my Master and Child Grid to ASP Razor but there was no definite example if how could I handle it in back end, and also my child grid contains drop down grid, so that would be a big re-do. And I also don't know if how can I pass customize parameter through it
I am desperate, I can't find any working reference except this one. but it's using odata, and I dont have child id to use as reference, since I am only using list which I retrieve in a user event.
Please help :'( I'm taking too much time for this one.
The solution is to define a transport properties, in order to fetch data from master, I only need to define the data and convert that to Jason.
take a look of these code:
function detailInit (e){
var msterRow = e.sender.items().index(e.masterRow).toString();
var grid = $("<div id='childGrid"+msterRow+"'
class=childGrid'/>").appendTo(e.detailCell).kendoGrid({
//data: e.data.ChildDetails,
transport: {
read: function (o) {
console.log("child read");
var data = e.data.ChildDetails.toJSON();
o.success(data);
},
update: function (o) {
console.log("child update");
var data = o.data,
arentItem = findByID(data.id);
for (var field in data) {
if(!(field.indexOf("_") === 0)){
arentItem[field] = data[field];
}
}
e.data.dirty = true;
saveChild(record, "#suffix", msterRow, "update");
o.success();
},
destroy: function (o) {
var parentItem = findByID(o.data.id);
preventBinding = true;
e.data.ChildDetails.results.remove(parentItem);
o.success();
saveChild(record, "#suffix", msterRow, "destroy");
},
create: function (o) {
console.log("child create");
var record = o.data;
record.id = index;
index++;
saveChild(record, "#suffix", msterRow, "create");
o.success(record);
}
},
schema: {
model: { fields: { foo: {--skip--}, bar: {--skip--} } }
},
toolbar: ["create", "cancel", "save"],
editable: "popup",
columns: [ --skip--]
}
Here's the working dojo snippet