Dynamically add fields that have javascript, to form - javascript

I have added fields to my form dynamically using a for-loop, which works fine. However, the fields i'm adding are supposed to be DatePickers and they require javascript as well. I've tried giving them a unique ID from the integer that the loops iterates through, but it does not seem to find them?
This is the view:
#model ProjectName.Models.ViewModels.GuestCreatorViewModel
#using Res = ProjectName.Resources.Resources
#for (int i = 1; i <= Model.NumOfGuests; i++)
{
<div class="row">
<div class="form-group">
#Html.Label(Res.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.Label(Res.Period, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.DateRange, new { id = "dateRangePicker" + i, htmlAttributes = new { #class = "form-control" }, #readonly = true })
#Html.ValidationMessageFor(model => model.DateRange, "", new { #class = "text-danger" })
</div>
</div>
</div>
<script type="text/javascript">
$('input[name="dateRangePicker'+#i'"]').daterangepicker();
$('#dateRangePicker'+ #i'').daterangepicker({
"showWeekNumbers": true
}, function (start, end, label) {
console.log('New date range selected: ' + start.format('YYYY-MM-DD') + ' to ' + end.format('YYYY-MM-DD') + ' (predefined range: ' + label + ')');
});
</script>
}
If I remove the "+ #i" in the javascript and "+ i" in the html.helper it works for the first row, but all rows/fields after does not work (I guess because the script is outside their scope). If I keep them, none of the fields work with the script.
Am I doing something wrong when dynamically naming them or something?
The DateRangePicker is taken from here, but I've also tried other datepickers where the same issue occurs.

First: This syntax is incorrect:
#Html.TextBoxFor(model => model.DateRange, new { id = "dateRangePicker" + i, htmlAttributes = new { #class = "form-control" }, #readonly = true })
It will render this useless attribute: htmlAttributes It should be:
#Html.TextBoxFor(model => model.DateRange, new { id = "dateRangePicker" + i, #class= "form-control", #readonly = true })
I guess it is a typo.
Second:
What you should do is generate all your HTML in the for loop, and use a single script tag after that to initialize the daterangepicker controls at once. You can get all inputs with a class instead of using their ids.
#{
int numOfGuests = 2;
}
#for (int i = 1; i <= numOfGuests; i++)
{
<div class="row">
<div class="form-group">
<div class="col-md-10">
#Html.TextBoxFor(model => model.DateRange, new { id = "dateRangePicker" + i, #class = "form-control custom-date-picker" , #readonly = true })
</div>
</div>
</div>
}
<script type="text/javascript">
$('input.custom-date-picker').daterangepicker({
"showWeekNumbers": true
}, function (start, end, label) {
console.log('New date range selected: ' + start.format('YYYY-MM-DD') + ' to ' + end.format('YYYY-MM-DD') + ' (predefined range: ' + label + ')');
});
</script>
Explanation:
Upon creating the datepickers I add to each one a custom css class:
custom-date-picker
After the for loop renders the HTML I create a
script tag and get all inputs with the selector
.custom-date-picker and create daterangepicker controls out of
them
P.S. I used a simplified version of your code for the sake of explanation.

I would not use the ID to assign the datepicker but a css class (even a not defined one, just for this purpose).
So you code could be something like this:
#class = "control-label col-md-2 ToBeDatePickered"
So you could try and use this simple selector:
$(".ToBeDatePickered").daterangepicker();
// ... and so on...
And the JS code should be outside the for statement, maybe in a document.ready function like this:
<script type="text/javascript">
$(document).ready(funtion() {
$(".ToBeDatePickered").daterangepicker();
// ... and so on...
});
</script>
Hope this helps

Related

.Net MVC Deselecting model checkboxes onclick in view

I have a model with two lists of SelectListItems:
public List<SelectListItem> ChosenLanguages { get; set; }
public List<SelectListItem> ChosenTemplates { get; set; }
I create checkboxes from those two lists for the user to interact with:
<div class="row">
<div class="col-lg-3">
<h5>Select languages for certificates</h5>
<div class="row" style="width:100%">
#for (int i = 0; i < Model.ChosenLanguages.Count; i++)
{
<div class="col-md-4">
#Html.CheckBoxFor(x => x.ChosenLanguages[i].Selected)
#Html.DisplayFor(x => x.ChosenLanguages[i].Text)
#Html.HiddenFor(x => x.ChosenLanguages[i].Value)
#Html.HiddenFor(x => x.ChosenLanguages[i].Text)
</div>
}
</div>
</div>
<div class="col-lg-3">
<h5>Select templates for certificates</h5>
<div class="row" style="width:100%">
#for (int i = 0; i < Model.ChosenTemplates.Count; i++)
{
<div class="col-md-5">
#Html.CheckBoxFor(x => x.ChosenTemplates[i].Selected)
#Html.DisplayFor(x => x.ChosenTemplates[i].Text)
#Html.HiddenFor(x => x.ChosenTemplates[i].Value)
#Html.HiddenFor(x => x.ChosenTemplates[i].Text)
</div>
}
</div>
</div>
</div>
Now I want to have a new checkbox that will "onclick" deselect all the checkboxes created above (as the use case requires the user to only select 1 language and 1 template):
#Html.CheckBoxFor(model => model.SerialOnly, new { htmlAttributes = new { #class = "form-control", #onclick = "clearSelected();" } })
My question is how do I go about deselecting each checkbox from the model in the view through an onclick? I have tried to use JavaScript and JQuery but I cannot figure out how I would access the individual checkboxes in the List..
I have tried to use the code from the most upvoted answer on this post (the accepted solution does not seem to fit my layout):
$(document).on('click', '#SelectAllCheckBox', function () {
$('.Publications input[type=checkbox]').toggle(this.checked);
});
Where I added the Publications name as a class to my checkboxes like so:
#Html.CheckBoxFor(x => x.ChosenTemplates[i].Selected, new { htmlAttributes = new { #class = "Publications" } })
And added the id to the new checkbox:
#Html.CheckBoxFor(model => model.SerialOnly, new { htmlAttributes = new { #class = "form-control", #id = "SelectAllCheckBox", #onclick = "clearSelected();" } })
But this did not work either. I know it will select all instead of deselect, but I just wanted to make the functionality work before changing it to deselect. Any ideas?

how to append a number of dropdowns on button click with each dropdown having different indexing in name attribute?

I am trying to append a number of dropdowns on Button click.These dropdowns should have proper indexing in its 'name' attribute.
This is the dropdown:-
<div id="dropdownDiv" style="display:none">
<div class="form-group">
#Html.LabelFor(model => model.PropertyInvestors, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.PropertyInvestors, (IEnumerable<SelectListItem>)#ViewBag.Investors, "Select Investor", htmlAttributes: new { #id = "dropdown",#name= "[#].PropertyInvestors", #class = "form-control",#onChange="dropdownChange()" })
#Html.ValidationMessageFor(model => model.PropertyInvestors, "", new { #class = "text-danger" })
</div>
</div>
</div>
This is the JS code that I am trying in order to clone the dropdown and replace its name attribute with desired indexing.
$('#addDropdown').click(function () {
var index = (new Date()).getTime();
var clone1 = $('#dropdownDiv').clone();
clone1.html($(clone1).html().replace(/\[#\]/g, '[' + index + ']'));
$('#field1').append(clone1.html());
});
Problem:- The dropdowns are being appended as they are clicked but their name attributes are same for all of the dropdowns produced due to which I cant postback the data to the controller.
While this problem can be solved by using dummy code and manipulating the Index no. by using JS, a good method would be to use Html.BeginCollectionItem() by creating a partial view for the dropdown and later making an ajax call to append the partial view to the main view. Refer to the answer HERE
You can replace ID and Name as follows:
$('#addDropdown').click(function () {
var index = (new Date()).getTime();
var clone1 = $('#dropdownDiv').clone();
$(clone1).find('select').attr("id", index);
$(clone1).find('select').attr("name", "PropertyInvestor[" + index +"]");
$('#field1').append(clone1.html());
});
JSFiddler: https://jsfiddle.net/qj24yybe/6/

Replace a div on a ajax call using javascript / Jquery

I need some help in order to replace some html inside a div with some other html which I get from the server when making the Ajax call.
To make this clear for you guys, I have the following code:
Code:
<div class="travel-container" id="travel-container">
<div class="travel-content">
#using (Html.BeginForm(new { id = "sbw_travel_form" }))
{
<div class="row">
<div class="routes small-12 large-6 column">
#Html.Label("Departure Route:", new { #class = "label-travel" })
#Html.DropDownListFor(m => m.DepartureRoute, routesSelectList, new { #class = "dropdown", #id = "Outbound-route" })
#Html.Label("Return Route:", new { #class = "label-travel" })
#Html.DropDownListFor(m => m.ReturnRoute, routesConverslySelectList, new { #class = "dropdown", #id = "Return-route" })
</div>
<div class="dates small-12 large-3 column">
#Html.Label("Departure Date:", new { #class = "label-travel" })
#Html.TextBoxFor(m => m.DepartureDate, new { Value = Model.DepartureDate.ToShortDateString(), #class = "textbox datepicker ll-skin-melon", #id = "departureDate" })
#Html.Label("Return Date:", new { #class = "label-travel" })
#Html.TextBoxFor(m => m.ReturnDate, new { Value = Model.ReturnDate.ToShortDateString(), #class = "textbox datepicker ll-skin-melon", #id = "returnDate" })
</div>
<div class="small-12 medium-6 large-3 columns"></div>
</div>
}
</div>
</div>
Here you see that I have put everything inside a class container called travel-container.
What I'm trying to do is to replace the div with the "routes" class with some same div tag when I get new html from the server. The problem is that I need to keep the rest of the html inside the container.
The ajax call code:
$.ajax({
type: 'POST',
url: "#Url.Action("FindReturnRoutes", "Travel")",
dataType: "html",
data: postData,
beforeSend: function () {
$(".travel-content").append(res.loader);
setTimeout(delay);
},
success: function (data) {
setTimeout(function () {
$(".travel-content").find(res.loader).remove();
$('.travel-container').html($(data).find(".travel-content"));
datepickerLoad();
Initializer();
}, delay);
}
});
Right now I'm using the find method to find the travel-content div and replace all the content within that div. Have tried putting .routes after and alone but none seem to work. Is find the right solution to use here?
All I want is to replace the routes div with the new one I get from the ajax call, but still keep the rest of the html without replaceing it all.
Following code snippet may be helpful for you.
$('.travel-container .routes').prepend($(data).find('.routes').html());
Can you try this please:
$('.travel-container .travelcontent').html(data);

Html.DropDownListFor and JavaScript Array

I've implemented Cascading Drop Down Lists on the Create View page of my MVC Asp.NET Application.
Unfortunately, I am having issues with selecting a value that is located in the JavaScript Array. I need to bind the selected value for the use of one of my controllers.
Right now my List populates, but I have no way to select it. Is there a way to move the counties[i] array from my JavaScript to the #Html.DropDownListFor() helper?
Thanks!
JavaScript:
<script src="#Url.Content("~/Scripts/jquery-1.10.2.min.js")"
type="text/javascript"></script>
<script language="javascript" type="text/javascript">
$(document).ready(function() {
$("#county").prop("disabled", true);
$("#StateLongName").change(function() {
if ($("#StateItems").val() != "Please select") {
var options = {};
options.url = "/County/GetCounties";
options.type = "POST";
options.data = JSON.stringify({ state: $("#StateLongName").val() });
options.dataType = "json";
options.contentType = "application/json";
options.success = function(counties) {
$("#county").empty();
for (var i = 0; i < counties.length; i++) {
$("#county").append("<option>" + counties[i] + "</option>");
}
$("#county").prop("disabled", false);
};
options.error = function() { alert("Error retrieving counties!"); };
$.ajax(options);
} else {
$("#county").empty();
$("#county").prop("disabled", true);
}
});
});
</script>
Controller:
//GET Counties for Cascading Dropdown List
public JsonResult GetCounties(string state)
{
var counties = db.countycigtaxes.Join(db.statecigtaxes,
cc => cc.stateid,
sc => sc.stateid,
(cc, sc) => new
{
cc,
sc
}).Where(co => co.sc.statefullname == state)
.Select(co => co.cc.countyfullname).ToList();
return Json(counties);
}
View Page:
<div class="form-group">
#Html.LabelFor(model => model.StateLongName, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.StateLongName, Model.StateItems, "Please select")
#Html.ValidationMessageFor(model => model.StateLongName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CountyLongName, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#*#Html.DropDownListFor(m => m.CountyLongName, )*#
<select id="county"></select>
#Html.ValidationMessageFor(model => model.CountyLongName)
</div>
</div>
I assume you mean the the selected value of the property CountyLongName is not posting back when you submit the form. You have commented out this line
#Html.DropDownListFor(m => m.CountyLongName, )
and used
<select id="county"></select>
If you want the manual version (I do not recommend this), then you need to add a name attribute that matches the property name so it can be bound by the ModelBinder
<select name="CountyLongName" id="county"></select>
But it is better to use the helper and pass it an empty SelectList
Html.DropDownListFor(m => m.CountyLongName, Model.CountryNames)
where Model.CountryNames is a property in you view model that is initialised to an empty SelectList
Note also options.type = "POST"; should be "GET" and the whole AJAX could be simplified to
$.get('#Url.Action("GetCounties","Country")', { state: $('#StateLongName').val() }, function(countries) {...
and theToList() is not required in the JsonResult method
This should set the option selected for you.
$("#county option[value='" + counties[index] + "']").attr("selected", "selected");

why ValidationMassage errors does not show in view, but shows in firebug?

hi i have a partial view that is loaded in main view by clicking "edit" or "create" button.
it hast some dropdownlist thas fill by ViewBags.
i have activated unobtrasive javascript in webconfig and use it in my partial view.
when i debug main view in firebug, DropDownList's validationMessage errors just shows in html part of console and doesn't show in view by
"#Html.ValidationMessageFor(m=>m.groupID)"
how can i solve it? Thanks.
Edited: Sample codes
<div class="editor-label">
#Html.LabelFor(model => model.InsuranceInsurerID)
</div>
<div class="editor-field">
#Html.DropDownList("InsuranceInsurerID", "Select...")
#Html.ValidationMessageFor(model => model.InsuranceInsurerID)
</div>
<div class="clr"></div>
<div class="editor-label">
#Html.LabelFor(model => model.InsuranceTypeID)
</div>
<div class="editor-field">
#(Html.Kendo().ComboBox()
.Name("InsuranceTypeID")
.HtmlAttributes(new { style = "width:210px" })
.Placeholder("Select...")
.DataTextField("TypeName")
.DataValueField("TypeID")
.Filter(FilterType.Contains)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetCascadeTypes", "Insurance");
});
})
)
#Html.ValidationMessageFor(model => model.InsuranceTypeID)
</div>
ViewBags:
var InsInsurer = db.INS_InsuranceWorkers
.Where(m => m.InsWorkerTypeID == 1 && m.InsWorkerCreateUserID == userid)
.Select(k => new { FullName = k.InsWorkerFirstName + " " + k.InsWorkerLastName,
InsInsurerID = k.InsWorkerID }).ToList();
ViewBag.InsuranceInsurerID = new SelectList(InsInsurer, "InsInsurerID", "FullName");
kendo dropdown gets list by its actions.

Categories