I have a set of list elements, that I create dynamically. Each of these list elements, contains an input text, whose value I want to pass to the controller.
HTML
<ul id="list"></ul>
<button id="add">Add</button>
<script>
var counter = 1;
$('#add').click(function () {
var text = '<input type="text" name="(what should I put here?)"></input>';
var li = '<li>' + text + '</li>';
$(li).appendTo('#list');
counter++;
return false;
});
</script>
View Model
public IEnumerable<string> list {get; set;}
...
How can I bind those values to my ViewModel implicitly? I have tried to use the counter variable to assign a name to each created element (like list[counter]), but on the controller side the list variable on my ViewModel still comes empty.
First I would base your counter on the amount of li's within your un-ordered list with:
$('#list > li').size()
Then in order to keep the model binder happy pre-fix your property with list:
'<input type="text" name="list[' + counter + ']"></input>'
The full code then becomes:
$('#add').click(function () {
var counter = $('#list > li').size();
var text = '<input type="text" name="list[' + counter + ']"></input>';
var li = '<li>' + text + '</li>';
$(li).appendTo('#list');
return false;
});
jsFiddle
Please note, you will have to change your view model property to an IList or List for indexing to work too:
public IList <string> list {get; set;}
Because your collection is for value type (string) only, then you can simply use
$('#add').click(function () {
var text = '<input type="text" name="list"></input>';
....
});
It is only necessary to include indexers when the property is a member of a complex object.
If you do include the indexer, it must start at zero and be consecutive (unless you also include a special hidden input for to identify the indexer). Your attempt at using list[counter] failed because the value of counter is initialized to 1 (it would have worked had you initialized it to var counter = 0;)
Related
I have a multiselect dropdown. All of its selected text and values should be displayed as each entry on other dropdown. I coded somewhat like this but its not working. All the selections of multiselect dropdown are appending on a single entry of the other dropdown. It is not displaying as separate entries.
#LstCashAccount is the multiselect dropdown and #ddlDefaultCash is the dropdown where entries selected in multiselect dropdown have to get affected
$('#LstCashAccount').change(function () {
$("#ddlDefaultCash").empty();
$("#ddlLoyaltyAcc").empty();
var CashAcc = "";
var CashAccId = $("#LstCashAccount").val();
CashAccIdSplit = CashAccId.splice(",")
CashAcc = $(this).find("option:selected").text();
CashAccSplit = CashAcc.split(".")
$("#ddlDefaultCash").append('<option class="InputDefCash" Id=' + CashAccIdSplit + '>' + CashAccSplit + '</option>');
});
So there are multiple issues here.
First, it's important to realize that the .append() function is what's actually creating your items. You only call this once, so expecting there to be multiple items is, frankly, a bit silly.
Second, you're using .splice() on a string, which isn't valid. I have a hunch you meant to do .split(), but without your HTML markup, it's a bit of a shot in the dark.
And finally, your CashAccSplit variable is (and, I assume, your CashAccIdSplit is supposed to be) an array. If you just concatenate this with a string, it will output the entire array.
If we clean this up, you might be looking for something more like the following...
$('#LstCashAccount').change(function () {
$("#ddlDefaultCash").empty();
$("#ddlLoyaltyAcc").empty();
var CashAcc = $(this).find("option:selected").text();
var CashAccId = $("#LstCashAccount").val();
var CashAccIdSplit = CashAccId.split(",")
var CashAccSplit = CashAcc.split(".")
//Use .each to iterate through the array, append each member as an item
$.each(CashAccIdSplit, function(index, item) {
$("#ddlDefaultCash").append('<option class="InputDefCash" Id=' + CashAccIdSplit[index] + '>' + CashAccSplit[index] + '</option>');
});
});
I have a dynamically generated grid with x number of textboxes that will be in it. As each textbox is generated, I give it an OnChange event that is a set function.
Html.TextBox(... new { #onchange = "ChangeItemQuantity(" + vm.ID + ", " + fk.id + ")" ...
So when it's rendered, it looks like this:
<input ... type="text" onchange="ChangeItemQuantity(1939, 3)" />
Then, in the script section:
function ChangeItemQuantity(ItemId, ForeignKeyId) {
...
}
In the ChangeItemQuantity() function, how would I also capture the new value of the textbox? I don't really want to use an id on the textbox, because it is part of a grid with many textboxes.
Should I pass it in as a parameter? If so, what would the syntax be of the code that renders the textbox?
Or, is there a way to capture is inside the javascript function?
Thanks!
If you want to store data in the html element why not use data- attributes?
Set them like so
#Html.TextBox(.... new { #class="someClass" data-vmId="vm.ID", data-fkId="fk.id" })
Then set a listener on that class
$('.someClass').change(function() {
var value = $(this).val();
var vmid = $(this).data('vmid');
var fkid = $(this).data('fkid');
}
am having Some kendoui listviews which consists of kendoui dropdown lists and i want to get those dropdown list selected values. To do this am trying,
$("#cnty1").val();
and here is my dropdownlist,i.e., list of countries coming from Database table,
<input select STYLE="width:90px;height:auto" id ="cnty1" data-bind="value:cnty1"
name="cnty1" data-type="string" data-text-field="cnty"
data-value-field="cntyid" data-source="sourcedata1" class="k-d"
data-role="dropdownlist" />
<span data-for="cnty1" class="k-invalid-msg"></span>
here cnty1 is the id of the dropdown list, but am not getting the value instead am getting "id" of the slected value but not the selected value.
And also if the value is not selected am getting the first value id by using $("#cnty1").val();
So, please suggest me a solution so that,
1) I should get only the Selected value and
2) Value of the dropdown list Only if the user selects a value from the list, but don't get the value of the list without selecting.
try this one.
<select STYLE="width:90px;height:auto" id ="cnty1" data-bind="value:cnty1"
data-text-field="cnty" data-value-field="cntyid" data-source="sourcedata1" data-role="dropdownlist" data-change="cntySelect" data-option-label="Select"></select>
function cntySelect(e) {
var dropDownVal = $("#cnty1").val();
alert(dropDownVal);
}
Use the following jquery to get selected value/text:
For value:
$("#cnty1 option:selected").val();
For text use:
$("#cnty1 option:selected").text();
Although this code is being used for FK JSON objects in KendoUI grid, the idea is similar. You have to bind the object on dropdown value selection. The dropdown essentially contains options that are your value ID's, not the objects themselves. Therefore, you have to iterate through the data source to find which object has been selected and then do the replacement in data model.
/**
* KendoDropDownEditor Class
* */
var KendoDropDownEditor = Class({
initialize: function (schema, gridId, readUrl) {
var readUrl = readUrl || base + schema.entityName + "/read";
this.dataSource = DataSourceGenerator.crudDS(schema, gridId, readUrl);
this.dataTextField = schema.model.dropDownTextField;
this.dataValueField = schema.model.id;
},
/**
*
* */
do:function (container, options) {
var self = this;
var a = $('<input data-text-field="' + self.dataTextField + '" data-value-field="' + self.dataValueField + '" data-bind="value:' + options.field + '"/>')
.appendTo(container)
.kendoDropDownList({
autoBind:false,
dataSource:self.dataSource,
close:function (e) {
$.each(self.dataSource.data(), function(key, value) {
if (value[self.dataValueField] == e.sender.value()) {
options.model[options.field] = value;
return false;
}
});
}
});
}
});
Also look at Knockout-Kendo, it could make your life easier.
I'm working in MVC and was trying to use jquery to perform the following, if there is an easier way i'd be happy to hear it...
I'm looking to have my form create dynamic input to produce something for example that could look like this: *i won't know how many subcat's they are going to enter nor how many main categories.
category0 <btnInsertSubCat0>
subcat0.0
subcat0.1
subcat0.2
category1 <btnInsertSubCat1>
subcat1.0
subcat1.1
<btbInsertNewCat>
I can produce a button that appends textboxes one after another as well as a button next to it but even if I use the .live attribute I can't get the subcat button to fire. Changed code around a lot and looked at different tutorial to no avail, fig. this would be semi easy to do?
jQuery(document).ready(function () {
var procID = 0;
var orgID = 0;
$('.clickme').live('click', function () {
var newItem = $("<input type='text' name='Procedure[" + procID + "]' value='Procedure[" + procID + "] />");
var newLabel = $("<br /><label id='Label[" + procID + "]' >ProcedureID: [" + procID + "]</label>");
var newDiv = $("<div class='objective'><b>Insert Objective</b>[" + procID + "." + orgID + "]</div>");
$("#procedureHolder").append(newLabel);
$("#procedureHolder").append(newItem);
$("#procedureHolder").append(newDiv);
procID++;
});
$('.objective').live('click', function () {
var newObj = $("<input type='text' id='Objective[" + (procID - 1) + "." + orgID + "]' >ObjectiveID: [" + (procID - 1) + "." + orgID + "]</label>");
$("#procedureHolder").append(newObj);
orgID++;
});
});
I edited my post, figured it out on my own how to utilize jquery to create an unlimited number of child dynamic textboxes. They all post back in the form collection as well. I figured out why the objectives weren't showing up, turns out i was declaring ID rather than Name. Thanks!
I've used the following approach for a dynamic search screen using ASP.NET MVC. Search options where managed in a database mapped to a product. This allowed the marketing team to tweak searching results and the search options in the admin section of the website. Essentially the approach was the following:
public class FormFieldCollection : List<FormField>
{
public string FormFieldType { get; set; }
}
public class FormField
{
public string Name {get;set;}
public string Type {get;set;}
public string Value {get;set;}
public bool IsChecked {get;set;}
}
public class FormFieldModel
{
public FormFieldCollection PaymentOptions { get; set; }
}
In the view generated from either custom Helper or use a foreach.
In your Controller action something like:
public ActionResult SomeActionMethod(FormCollection formCollection)
{
//search through the results, map back to class or loop through key value pairs.
}
View Code, obviously include some nice html markup to format the form.
#Model FormFieldCollection
#{
View.Title = "Form";
Layout = "~/Views/Shared/_defaultMaster.cshtml";
}
#foreach(var formField in Model){
<input type="#formField.Type" id="#formField.Name" name="#formField.Name" value=""#formField.Value"" />
}
#using (Html.BeginForm("SomeActionMethodAdd", "ControllerName", FormMethod.Post))
{
//Submit form to
Field Name: <input type="text" value="" /> * must be unique
<input type="submit" value="Submit" />
}
Syntax mightn't be perfect just going of memory for razor.
I'm passing a List to an MVC view and generating checkboxes for each object in the list (The checkboxes are named t.Name).
I'd like to be able to tell which checkboxes were checked once the form is posted. However, I'd like to avoid using the FormCollection object. Is there any way to do this?
Set the name of your checkboxes to something like "MyObject[" + index + "].Checked", and for each checkbox also put a hidden input field named something like "MyObject[" + index + "].Name" with the value set to t.Name.
If you name your fields like that, the default model binder can take your form values and map them to a list of objects with a Name property and a Checked property.
I would try something like the following:
<% foreach(var t in Model)
{ %>
<div>
<%= Html.Hidden("MyObject[" + index + "].Name", t.Name, new { id = "MyObject_" + index + "_Name" }) %>
<%= Html.Checkbox("MyObject[" + index + "].Checked", false, new { id = "MyObject_" + index + "_Checked" }) %>
</div><%
} %>
I use the anonymous type with id property so that the MVC framework components don't generate HTML elements with invalid id values, but it isn't really necessary.
Your action handling the post would look something like this:
[HttpPost]
ActionResult MyAction(IList<MyObject> objects)
{
foreach (MyObject obj in objects)
{
if (obj.Checked)
{
// ...
}
else
{
// ...
}
}
return View();
}