Filling MVC DropdownList with AJAX source and bind selected value - ajax

I have view for showing Member details. Inside there is an EditorFor element which represents subjects taken by the member.
#Html.EditorFor(m => m.Subject)
Inside the editor template there is a Html.DropDownListFor() which shows the selected subject and button to delete that subject
I am using an Html.DropDownListFor element as :
#Html.DropDownListFor(m => m.SubjectID, Enumerable.Empty<SelectListItem>(), "Select Subject",
new { #class = "form-control subjects" })
The second parameter(source) is set empty since I want to load the source from an AJAX request; like below:
$.getJSON(url, function (response) {
$.each(response.Subjects, function (index, item) {
$('.subjects').append($('<option></option>').text(item.Text).val(item.ID));
});
// code to fill other dropdowns
});
Currently the html loads before the dropdowns are filled. So the values of all subject dropdowns are set to the default "Select Subject". Is there a way around this or is it the wrong approach?
Note: There are a number of dropdowns in this page. That's why I would prefer to load them an AJAX request and cache it instead of putting in viewModel and filling it for each request.
** EDIT **
In AJAX call, the action returns a json object containing dropdowns used across all pages. This action is decorated with [Output Cache] to avoid frequent trips to server. Changed the code in $.each to reflect this.

You can initially assign the value of the property to a javascript variable, and use that to set the value of the selected option in the ajax callback after the options have been appended.
// Store initial value
var selectedId = #Html.Raw(Json.Encode(Model.Subject.SubjectID))
var subjects = $('.subjects'); // cache it
$.getJSON(url, function (response) {
$.each(response, function (index, item) {
subjects.append($('<option></option>').text(item.Text).val(item.ID));
});
// Set selected option
subjects.val(selectedId);
});
However its not clear why you are making an ajax call, unless you are generating cascading dropdownlists which does not appear to be the case. What you doing is basically saying to the client - here is some data, but I forgot to send what you need, so waste some more time and resources establishing another connection to get the rest of the data. And you are not caching anything despite what you think.
If on the other hand your Subject property is actually a collection of objects (in which case, it should be Subjects - plural), then the correct approach using an EditorTemplate is explained in Option 1 of this answer.
Note also if Subject is a collection, then the var selectedId = .. code above would need to be modified to generate an array of the SubjectID values, for example
var selectedIds = #Html.Raw(Json.Encode(Model.Subject.Select(x => x.SubjectID)))
and then the each dropdownlist value will need to be set in a loop
$.each(subjects, function(index, item) {
$(this).val(selectedIds[index]);
});

If your JSON tells you what option they have selected you can simply do the following after you have populated your dropdown:
$('.form-control.subjects').get(0).selectedIndex = [SELECTED_INDEX];
Where [SELECTED_INDEX] is the index of the element you want to select inside the dropdown.

Related

Get all business recommended fields in subgrid

How do I check if a particular field or column of a subgrid is business recommend or not? I want to do this using a web resource. Also due to some requirements, I will have to use the execution context of the form where the subgrid is present and not of the subgrid itself.
It is a little tricky because at the time that the form loads, the subgrid does not have data. So you have to use the Form's load event to attach a load event to the subgrid.
This is described in this MS Docs Page. You can do this like
function attachGridEvent(executionContext)
{
var formContext = executionContext.getFormContext();
var gridContext = formContext.getControl("gridCategories");
// We have the grid, now add a "load" event handler
gridContext.addOnLoad(MyGridLoadedEvent);
}
Now you've got a 'load' event for your grid so you can iterate through its rows and examine its data
I haven't been able to get this to work for subgrids that don't contain data
I get the first row in the sub grid. Once I have that we can loop through each of the row's attributes. Each attribute has the following methods:
getName Returns the logical name of the attribute of a selected grid
row.
getRequiredLevel Returns a string value indicating whether a
value for the attribute is required or recommended.
setRequiredLevel Sets whether data is required or recommended for the
attribute of a selected grid row before the record can be saved.
getValue Retrieves the data value for an attribute.
setValue Sets the
data value for an attribute.
MS Docs Page
I'm using some modern browser features (map, =>) but this code should work for you
function MyGridLoadedEvent(evt)
{
var gridContext = evt.getEventSource();
var rows = gridContext.getGrid().getRows();
if (rows.getLength() > 0)
{
let rowAttributes = rows.getByIndex(0).getAttribute();
let mappedResults = rowAttributes.map(x => x.getName() + " : " + x.getRequiredLevel());
alert(mappedResults);
}
}

need to get value of dropdown menu without using onChange callback - (material-ui reactjs)

i am using material UI dropdown component and trying to run a callback function only when user fills all the form and submits the form. On the call back function i intend to collect all the form field and generate url to call to api.
My problem is that i can not use onChange as stated solution in #560 as i want to collect all the detail only when user clicks the submit button. It is also weird that at the moment, i am able to get value of all the other form element like slider, textfield which uses material-ui but only dropdown does not seem to be working.
My call back function:
handleFilter: function(event){
event.preventDefault();
var location = this.refs.location.getValue();
var posted_date = this.refs.posted_date.getValue();
var radius = this.refs.distance.getValue();
var salary = this.refs.salary.getValue();
var jobtype = this.refs.jobtype.getValue();
console.log(jobtype);
}
In the above function "location, posted_date, radius, salary" returns value but "jobtype" which happens to be dropdown does not seem to return any value. It returns this error in console:
"Uncaught TypeError: this.refs.jobtype.getValue is not a function"
Here is my dropdown component :
<DropDownMenu menuItems={menuItems} ref="jobtype" />
May not be the right way but i figured out that
console.log(this.refs.jobtype) (jobtype is the refs value of dropdown in my case)
was giving the following result.
R…s.c…s.Constructor {props: Object, context: Object, state: Object, refs: Object, _reactInternalInstance: ReactCompositeComponentWrapper}
Inpecting it i found value of payload index (index number of selected item) inside state object within "selectedIndex" property. I used following code to access the selected index:
var jobtype = this.refs.jobtype.state.selectedIndex;
If there is a better way to do this please suggest.

How to make Ext.Ajax.request only after form fields are loaded completely

I have a function which uses following code to fetch form values-
var formValues = this.myForm.getForm().getValues();
MyForm contains a combobox which loads with form. (There are two separate requests for combo load and form load)
As these two requests are loading at the same time, above code do not return combo values as they are still loading.
Is there any way to check whether combo values are loaded and then only send ajax request for form load so that above code will have all form values?
Edited:
LoadComboBox function just fills the data with some store.
Following is the code for form load-
loadFormGrid: function (){
var allValues = this.myForm.getForm().getValues(); // this do not consider combobox values
Ext.Ajax.request({
params: {action: 'getList', data : allValues },
// ... some code
});
}
I would do something like:
On the success event of the combo box load, call the load method of the form/make your ajax request to populate the fields of the form.
EDIT:
Here is what I mean:
The place where you instantiate your ComboBox probably looks like:
var combo = new Ext.form.ComboBox({
store : new someStoreType({
//add to catch the loaded event
listeners : {
'load' : function(store, recs, options){
loadFormGrid();
}
}
})
});
The store listener above ('load') will catch when the combo box is loaded and will call the function to populate/load the form.

Auto Complete for Generic list MVC 3

I have a Generic list in my Model class. I want to have a textbox with autocomplete in my view which fills data from the generic list. How can I do this?.
For this you will need
Function on server side which will return list of matching data and will accept string entered by the user.
Something like this
public JsonResult AutoComplete(string input)
{
//Your code goes here
}
In the View, for the text box you need to bind KeyDown event. You can take help of jQuery for this. On key down handler you will make an Ajax call to the function you have defined in the Controller. Some thing like this:
$.ajax({
url: '#Url.Action("AutoComplete", "ControllerName")',
data: 'input=' + sampleInput,
success: function (data) {
//Show the UL drop down
},
error: function (data) {
// Show Error
}
});
In response you will get list of strings, which you will need to bind to some html element like "UI". Once done, display this UI with proper CSS below the text box. Using jQuery, you can retrieve the pixel location of text box too.
You can not use Asp.Net Auto Complete box in your project as you are developing app in MVC (no viewstate). I hope you get the idea.
You can use JQuery Autocomplate.
To fill the list, you can populate the data from you object.
I can't remember the exact Razor syntax, but you can refer to this:
//data is your Model object of type List<String>
var listString = [#foreach(x in data) { '#x',}];
$( "#dataList" ).autocomplete({
source: listString
});
<input id="dataList">
JQuery Autocomplte
http://jqueryui.com/demos/autocomplete/
This is client side auto complete, I can provide server side if you need.

How do i automatically append column names to post data sent to php when grid loads or refreshes?

I'm new to jqGrid and jquery and i'm learning as fast as i can but i still am a little lost about how to some things like how to append addition information to the post data in jqgrid that gets sent to php.
It would be nice for the php script to know what columns the grid wants when it initially loads or you press the jqgrid refresh/reload button.
I know i can use the postData option: postData:{name:val,,,}, but i was hoping to just automatically pull the column names from the colModel definitions using this function...
postData: function(){
colmodel = $('#tab4-grid').jqGrid('getGridParam','colModel');
colarray = '{';
for (var i in colmodel) {colarray += '"'+colmodel[i].name+'":"'+colmodel[i].name+'",';}
colarray += '}';
return colarray;
},
so i would not have to spell them out manually again. However, while the function produces the correct code, it's not getting posted. I can't seem to figure out the problem. Can someone help please?
thanks.
The first thing which you have to do is to rewrite
postData: function() { ... }
to
postData: {
myColumnsName: function() { ... }
}
jqGrid already send some standard parameters to the server (page, rows ,...). With the code above you will add and additional parameter with the name myColumnsName which you can fill in any way inside of the function body.
You current implementation is very dirty. You don't define local variables colmodel and colarray. Moreover you try to serialize array of strings as object ('{}') and not as array ('[]'). You should not use for (var i in colmodel) construction if you enumerate array items for (var i=0; i<colmodel.length; i++) is better. Additionally 'colModel' contain some column names ('rn', 'cb', 'subgrid') which you should skip in the enumeration. You can define as var colNames = []; and use colNames.push to fill it. Then you can use standard JSON.stringify method from json2.js to convert array to the JSON string.

Resources