How to pass dropdown list selected value in knockout function? - asp.net-mvc

I have to pass the dropdown selected value in knockout function. I have crated the razor syntax for that:
<div class="row">
#Html.LabelFor(m => m.FilterByType, htmlAttributes: new { #class = "label" })
#Html.DropDownListFor(m => m.FilterByType, new SelectList(Model.aspNetUser, "FilterByType", "FilterByName"), new { #class = "selectBox", #id = "aspnetUsersType", #data_bind = "event: {change: getData(0,'','',size,index,'')}" })
<input type="hidden" id="filterByType" name="filterByType" value="">
</div>
Following is my knockout function:
self.getData = function (filterbytype, fromdaterange, todaterange, pageSize, page, searchText) {"some task"}
How do I pass the selected value in the getData? Right now I am passing 0 as a filterbytype.

The objects can be passed from server to client using JSON, and binded to a property of type observableArray. Then bind this property to a html element using foreach binding. You can see an example here:
http://knockoutjs.com/documentation/foreach-binding.html

Suppose are using this following code in ur HTML
<select data-bind="options: operations, value: self.selectedOperation">
Make sure that You must be using these variables as ko.observable() type
so ur JS code will look like this
var self = this;
self.selectedOperation = ko.observable("Option1"); // with self u can use more variables and here selectedOperation will be containing the choosen value you want and you can pass it wherever u want
var operations = ko.observableArray(["Option1", "Option2", "option3", "Opt4"]); // dropdown List
Now its up to you how you are going to use that variable..

Related

Disabled property not working for ListBoxFor and DropDownListFor

I have a web page that dynamically creates components by rendering them through a RenderPartial Html Helper like this
Html.RenderPartial("_UploadStaticField", config);
Within the config object is a field called 'isUnderReview'. When this is set to true the components should be disabled by using the code below
//Single selection
<div class="editor-section">
<div class="label">
#Html.DisplayEditLabel(Model.Label, Model.Required.Value)
</div>
<div class="field large-text-field">
#Html.DropDownListFor(m => m.SelectedListOptionID, new SelectList(Model.ListOptions, "ID", "Name", Model.SelectedListOptionID).OrderBy(l => l.Value), new Dictionary<string, object>{
{"id", "staticField_" + Model.ID}})
</div>
</div>
<script>
$(document).ready(function () {
if ("#Model.IsUnderReview" == "True") {
document.getElementById("staticField_" + "#Model.ID").disabled = true;
}
});
</script>
and..
//Multiple selection
<div class="editor-section">
<div class="label">
#Html.DisplayEditLabel(Model.Label, Model.Required.Value)
</div>
<div class="field large-text-field">
#Html.ListBoxFor(x => x.SelectedRoles, filetypes, new { #class = "multiselectFileTypes" , id = "staticFieldM_" + Model.ID})
</div>
</div>
#Scripts.Render(BundleConfig.Scripts_MultiSelect)
<script>
$(document).ready(function () {
if ("#Model.IsUnderReview" == "True") {
document.getElementById("staticFieldM_" + "#Model.ID").disabled = true;
}
});
</script>
The code works to the point that the methods run but the components are still able to be used. Is there a way of cancelling any users selections which will serve as disabling as the values wont change?
Scripts should never be in partials (you potentially generating multiple inline scripts that may cause other problems, especially with the bundle). However a script is not even necessary for this, you can use a simple if statement or conditional attributes to generate what you want.
When you say "but the components are still able to be used", I'm guessing that your using a plugin to generate controls as suggested by Scripts.Render(BundleConfig.Scripts_MultiSelect) which will be hiding the original <select> element and generating its own html which is why it still interactive.
But the next problem is that disabled controls do not post back a value, so the vales of SelectedListOptionID and SelectedRoles will be their default, possibly resulting in your app failing depending on the code in your POST method.
Move the #Scripts.Render() into you view or layout, delete the scripts to disable the element and then change the partial to
#if(Model.IsUnderReview)
{
#Html.HiddenFor(m => m.SelectedListOptionID) // if you want the value to be posted
// add an element to display the Name associated with the SelectedListOptionID
// if necessary, for example your view model might include a property
// string SelectedListOptionName
}
else
{
#Html.DropDownListFor(m => m.SelectedListOptionID, new SelectList(Model.ListOptions, "ID", "Name").OrderBy(l => l.Value))
}
Side notes:
There is no reason to add you own id attribute (the
DropDownListFor() method generates <select
id="SelectedListOptionID" ... >
Remove the last parameter of the SelectList constructor
(Model.SelectedListOptionID) - its ignored by the
DropDownListFor() method. I also recommend your model contains an IEnumerable<SelectListItem> OptionsList property and you populate that in the controller so that it can simply be #Html.DropDownListFor(m => m.SelectedListOptionID, Model.OptionsList)

mvc option with html content

mvc option with html content
how to write/render
<select>
<option><span style="">Hi</span></option>
<option><span style="">Hi1</span></option>
<option><span style="">Hi2</span></option>
</select>
using #html.DropDownList()
--------Update-------------
i want to use html formatted text in option
when i passed it from modal, it was showing in dropdown list
<span style="">Hi</span>
<span style="">Hi1</span>
<span style="">Hi2</span>
here the span style="" is html it is not string, and the list is coming from controller
Use SelectItem in the code, insert options in that list, provide another property for selected item on Post using passing it to the view and use #Html.DropDownListFor(x => x.SelectItem) a simple example can be
#Html.DropDownListFor(model => model.Package.State, new SelectList(
new List<Object>{
new { value = 0 , text = "Red" },
new { value = 1 , text = "Blue" },
new { value = 2 , text = "Green"}
},
"value",
"text",
2))

New value in HTML.DropDownListFor(...) not setting in Controller [Post] method?

Hopefully someone can see how to go about this, because I've tried everything I can think of. When the Create() View in my MVC5 application loads I first populate several [SelectList(...)]'s in my Controller (ex.):
ViewBag.Model_Id = new SelectList(db.DBT_MODELS.OrderBy(x => x.MODEL_DESCRIPTION), "MODEL_ID", "MODEL_DESCRIPTION");
I then on my Create() View use this [SelectList(...)] to Populate an Html.DropDownListFor(...):
<div class="form-group">
<span class="control-label col-md-2">Model:</span>
<div class="col-md-4">
#Html.DropDownListFor(model => model.MODEL_ID, (SelectList)ViewBag.Model_Id, htmlAttributes: new { #class = "form-control dropdown", #id = "selectModel" })
#Html.ValidationMessageFor(model => model.MODEL_ID, "", new { #class = "text-danger" })
</div>
<div class="col-md-2">
<div class="btn-group">
<button id="createNewModel" type="button" class="btn btn-success" aria-expanded="false">CREATE NEW</button>
</div>
</div>
<div class="col-md-4">
<div id="createModelFormContainer" style="display:none">
<form action="/createNewModel">
<input type="text" id="textNewModel" name="model_description" placeholder="New Model" />
<input type="button" id="submitNewModel" value="Submit" />
<input type="button" id="cancelNewModel" value="Cancel" />
</form>
</div>
</div>
</div>
Simple enough, and this all works as expected. The problem lies in a bit of extended functionality I've tried to incorporate. My main class has several of these properties which are basically Foreign Key's in my DB. When a User goes in to Create/Edit() an entity in my main Model, I wanted to allow them to be able to add new entities to these foreign tables without needing to navigate away from the current View.
As such, I added (for each foreign property, using (Model) as an example) the code shown above and again directly below with a button to Show/Hide a small form for users to insert a new value and have it added to the DropDownList:
<div class="col-md-2">
<div class="btn-group">
<button id="createNewModel" type="button" class="btn btn-success" aria-expanded="false">CREATE NEW</button>
</div>
</div>
<div class="col-md-4">
<div id="createModelFormContainer" style="display:none">
<form action="/createNewModel">
<input type="text" id="textNewModel" name="model_description" placeholder="New Model" />
<input type="button" id="submitNewModel" value="Submit" />
<input type="button" id="cancelNewModel" value="Cancel" />
</form>
</div>
</div>
My submitNewModel() click event below gets the user's inputted new value and then uses a JSON call to a Controller Method to add it in the Database Table. This new value (and new ID for it) are then returned, the form for the DropDownList is reset, and I set the DropDownList's current value as the newly added one:
$('#createNewModel').click(function () {
$('#createModelFormContainer').show();
})
$('#cancelNewModel').click(function () {
$('#createModelFormContainer').hide();
})
$('#submitNewModel').click(function () {
var form = $(this).closest('form');
var data = { description: document.getElementById('textNewModel').value };
$.ajax({
type: "POST",
dataType: "JSON",
url: '#Url.Action("createNewModel", "INV_ASSETS")',
data: data,
success: function (resp) {
if (resp.ModelExists)
{
alert("Model [" + resp.Text + "] already exists. Please select from the DropDown.");
} else {
$('#selectModel').append($('<option></option>').val(resp.MODEL_ID).text(resp.Text));
form[0].reset();
$('#createModelFormContainer').hide();
var count = $('#selectModel option').size();
$('#selectModel').prop('selectedIndex', count - 1);
$('#selectModel').val(resp.MODEL_ID);
//document.getElementById('selectModel').value = resp.MODEL_ID; - Shows dropdown as blank [ ] once executed.
}
},
error: function () {
alert("ERROR - Something went wrong adding new Model [" + resp.Text + "]!");
$('#createModelFormContainer').hide();
}
});
//reloadForNewEntity();
});
The createNewModel() method that is called in my Controller:
public JsonResult createNewModel(string description)
{
DBT_MODELS model = new DBT_MODELS()
{
// ID auto-set during save.
MODEL_DESCRIPTION = description.Trim(),
CREATED_DATE = DateTime.Now,
CREATED_BY = System.Environment.UserName
};
var duplicateModel = db.DBT_MODELS.FirstOrDefault(x => x.MODEL_DESCRIPTION.ToUpper() == model.MODEL_DESCRIPTION.ToUpper());
try
{
if (duplicateModel == null)
{
if (ModelState.IsValid)
{
db.DBT_MODELS.Add(model);
db.SaveChanges();
// Ensure the [model.ID] is properly set after having been saved to and auto-generated in the database.
model.MODEL_ID = db.DBT_MODELS.FirstOrDefault(x => x.MODEL_DESCRIPTION.ToUpper() == model.MODEL_DESCRIPTION.ToUpper()).MODEL_ID;
}
}
else
{
model = duplicateModel;
}
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
return Json(new { ID = model.MODEL_ID, Text = model.MODEL_DESCRIPTION, ModelExists = (duplicateModel != null) }, JsonRequestBehavior.AllowGet);
}
Visually speaking, everything works as intended up to this point. The problem is when I go to Save the main entity I am Creating/Editing.
Any value that was already in the Foreign Tables, and thus in the DropDownList when the View loads, saves just fine; but if I add a new Foreign Table value for these main entity properties (though visually added and the currently selected values for the individual DropDownLists) the [POST] method then executes with each foreign id value set as 0 (ex. MainClass.Model_ID = "0" vs expected MainClass.Model_ID = "625", MainClass.Type_ID = "0" vs expected MainClass.Type_ID = "17", MainClass.Location_ID = "0" vs expected MainClass.Location_ID = "82", etc.)
Basically if the value selected in the Html.DropDownListFor() is one of my newly added values, the POST controller method always renders the MainClass.*_ID value which the selected Html.DropDownListFor() value corresponds to as "0".
Can anyone point me to how to get this working? I have tried:
Changing how my JavaScript sets the value in the DropDownList after the the JSON call to my Controller Actions returns (ex): //document.getElementById('selectModel').value = resp.MODEL_ID; - Shows dropdown as blank [ ] once executed. vs $('#selectModel').val(resp.MODEL_ID); which visually renders the expected new value in the DropDownList.
On return from the Controller method, setting a new ViewBag variable and then hoping to reference the saved value in the POST method (did not work, the JavaScript rendered my #Viewbag.PostModelID = resp.ModelID as "= resp.ModelID" and threw many expected errors).
EDIT:
[Redacted for N/A]
EDIT2: Good to go. Thanks everyone for the suggestions!
The json data you are returning from your action method is in this format.
{
"ID": 24,
"Text": "IOS",
"ModelExists": false
}
But in your code, you are trying to access MODEL_ID property which does not exist in the resp object.
$('#selectModel').append($('<option></option>').val(resp.MODEL_ID).text(resp.Text));
Change your code to use ID property value
$('#selectModel').append($('<option></option>').val(resp.ID).text(resp.Text));
$('#selectModel').val(resp.ID);
In your controller where you create the new model.. your json object that you're returning is ID, Text, ModelExists, but in your javascript you're setting the val property of the new <option> to MODEL_ID.. these 2 need to match..
So change your javascript to be
.val(resp.ID)
or change the return value in your controller action to
return Json(new { MODEL_ID = model.MODEL_ID, Text = model.MODEL_DESCRIPTION
You're also referencing MODEL_ID here
$('#selectModel').val(resp.MODEL_ID);
so make sure if you don't change your controller action, you update this also

MVC Radiobutton default value did not set after knockout data-bind

I am using MVC strongly typed view to generate two radio buttons
<div>
#Html.LabelFor(model => model.Eligible)
#Html.RadioButtonFor(model => model.Eligible,"true", new { id="yes", data_bind = "checked: completeVM.Eligible " })
#Html.Label("yes", "YES")
#Html.RadioButtonFor(model => model.Eligible, "false", new {id="no", data_bind = "checked: completeVM.Eligible " })
#Html.Label("no", "No")
</div>
If I don't use data_bind, when the page loads, the 'No' radio button will be set by default. But after I add data_bind, neither radio button is checked. I noticed in my view model, the Eligible was displayed as :"Eligible": false; if I check 'No' button, it will display as "Eligible":"false". How can I fix this so that when the page loads, the 'No' button will be checked by default. Thanks
This is a common problem. Radio button values are always a string. Yet you want boolean behavior. The easiest fix is to use an extra computed observable to do the translation for you:
Assuming 'this' points to your viewmodel:
this.EligibleRadioHelper = ko.computed({
read: function () {
return this.Eligible().toString();
},
write: function (value) {
this.Eligible(value === 'true');
},
owner: this
});
Bind against this new helper:
data-bind="checked: completeVM.EligibleRadioHelper"
When you want the boolean value (for logic or for persisting) use your original observable.
You also can try using the checkedValue binding available in knockout 3 without the need to write a computed function for your view model.
Your code will become something like this:
<div>
#Html.LabelFor(model => model.Eligible)
#Html.RadioButtonFor(model => model.Eligible,"true", new { id="yes", data_bind = "checked: completeVM.Eligible, checkedValue: true" })
#Html.Label("yes", "YES")
#Html.RadioButtonFor(model => model.Eligible, "false", new {id="no", data_bind = "checked: completeVM.Eligible, checkedValue: false " })
#Html.Label("no", "No")

Razor CheckBoxFor conditionally check and un-check in view

In my view I have,
#Html.CheckBoxFor(m => m.IsExist, new { #id = "IsExist" })
In my Model I have IsExist value from DB. Either true or false.
Now how can I 'Check' or 'Uncheck' the option, based on the true or false value in IsExist.
I expected, on binding by default the check box takes the value of Model. Howeverr that is not happening.
How can i achieve it?
Here how i achieved it
#Html.CheckBox("VC",(item.isVC=="Y") ? true : false)
where my item.isVC has value "Y" or "N"
Below snippet indicates an alternate way of having checkbox created and conditionally making it checked/unchecked. The following approach is also useful to get the value of checkbox by traditional approach using jquery.
#model myproject.Models.StudentModel
<div class="row">
<label class="checkbox-inline">
<input type="checkbox" name="selfStudy" checked="#Model.IsExist"><b>Self Study</b>
</label>
</div>
You can do this to check a checkbox :
if (Model.IsExist) {
#Html.CheckBoxFor(m => m.IsExist, new { #id = "IsExist", "checked" = "checked"})
}
Hope it's help

Resources