Angular Select NgOptions double selecting when directive compiles - javascript

I am working on a dynamic form that populates a dropdown conditionally based on another input. I have written a directive because the data that comes back will also carry validation rules that need to be applied. However when i apply the validation rules to the dropdown and recompile the select options are borked. The final HTML looks like this:
The questions on the form can depend on another to be answered in a very specific way before they appear. This dropdown for example depends on the country selected but can be required or optional depending on what country is selected. The data coming back from my server gives me a validation object that contains validation information for the input field such as:
var question = scope.question;
var input = element.find('select');
if (question.validation.required) {
if (!input.attr('required')) {
input.attr('required', question.validation.required);
}
}
$compile(input)(scope);
The standard <option value="?" selected="selected"></option> is put in but when the question the dropdown depends on triggers the watch and a request happens for the dropdown the server returns and the backing select values are changed but the HTML output results as seen above all the items that are set to selected are unselectable and the form validation fails.
function answerMatch(countryCode) {
sectionService.getDivisionsByCountryCode(countryCode).then(function (response) {
scope.question.selectValues = response.data;
element.show();
});
}
and an HTML snippet for good measure
<select id="question{{question.questionId}}" name="answer" ng-model="question.value" ng-options="value.text for value in question.selectValues" class="form-control">
</select>

Related

jQuery validator is validating against no longer existing form elements after ajax call

I have a form which dynamically adds or removes input fields depending on certain selections which have been made by the user.
The basic form looks like this, simplified:
<form action="...some/path..." id="MyForm" method="post">
<!-- the first input field is a select list, depending on the selected option, an ajax call will be made to update the div below with new input fields -->
<select name="selectList">
<option>#1</option>
<option>#2</option>
<option>#3</option>
<option>...</option>
</select>
<div id="UpdateThisSection"></div>
<input type="submit" value="Submit">
</form>
Depending on which option the user picks from the select list, the user will be presented with different input fields, which are rendered in the #UpdateThisSection div.
The input fields for option #1 would be:
Date Field (required), so the required attribute is set to the input field, as well as the custom data-type="Date" attribute
Text (optional), no required attribute is set
The input fields for option #2 would be:
Text (optional), no required attribute set
Text (optional), no required attribute set
The input fields for option #3 would be:
Text (optional), no required attribute set
Numeric (optional), required attribute set, as well as the custom data-type="Numeric" attribute
The jquery validation is implemented like this:
$("#MyForm").validate();
$.validator.addMethod("usDate",
function (value, element) {
return value.match(/^(0?[1-9]|1[0-2])[/., -](0?[1-9]|[12][0-9]|3[0-1])[/., -](19|20)?\d{2}$/);
},
"Please enter a valid date."
);
$("input[data-type='Date']").each(function () {
if ($(this).prop("required")) {
$(this).rules("add",
{
usDate: true
});
}
});
$("input[data-type='Numeric']").each(function () {
$(this).rules("add",
{
number: true
});
});
Validation works perfectly fine if I open the form and select any option. The form is being validated the way it should. However, if I change my mind and select a different option from the dropdown, the form is not validating correctly anymore. On submit, I see that the form is being validated with the previous form's requirements.
Looking at the $("#MyForm").validate() object on the console the invalid as well as the submitted property are still holding information of the previous form. What is the easiest way to reset the validator whenever a new ajax call load a new form element?
I tried to reset the form using $("#MyForm").validate().resetForm(); but it didn't clear the properties mentioned above.
Trying to clear the validation as suggested in this stackoverflow-post didn't resolve the issue for me either.
What is the easiest way to reset the validator whenever a new ajax call load a new form element?
In the Ajax success callback, remove all static rules from an element
$("#MyForm").rules( "remove" );
// Then add or re-add some static rules...
Sorry... can't easilly recreate that for a demo.

How to separate by pipe for multiple select in hidden field

I have a form that has 3 drop downs to make selections, the first drop down allows the user to select a specific Type, the second box, the user must select a date which will then present users with the filtered options on the 3rd drop down which is done in Jquery. I had it working where the user only selects one option in the 3rd drop down.
Now I would like the user to select multiple options. The code below is what I used to get the single selection to update the hidden field and pass via form submission.
The below code minus the ".join('|')" outputs the values into the hidden field then it gets passed into a data storage via POST.
This is my code:
$('#TopicID').on('change',function()
{ TIDval.val( $(this).find(':selected').text().join('|') );
});
I tried several versions to get it to work if I remove the ".join('|')" the output gives me all of the values concatenated.
Value 1: tree
Value 2: boat
Value 3: car
The output is as follows: treeboatcar
but I need: tree|boat|car
I have updated my new code to reflect the solution suggested by Loading... in this thread to the following.
$('#TopicID').change(function(){
var selectedText = $(this).find(':selected').map(function(){
return $(this).text(); //$(this).val()
}).get().join('|');
$("#TopicID_value").text(selectedText);
});
Which now updates the hidden field value correctly with the pipe separated values but the value is no longer passed in the POST call when submitted in the form.
The hidden field
In firebug I see the value being updated properly when I select one or multiple options but for some reason the value gets lost in the submission process. I don't see much of a different where that could happen.
Use map()
$('#TopicID').change(function(){
var selectedText = $(this).find(':selected').map(function(){
return $(this).text(); //$(this).val()
}).get().join('|');
console.log(selectedText);
});
$('#TopicID').change(function(){
var selectedText = $(this).find(':selected').map(function(){
return $(this).text(); //$(this).val()
}).get().join('|');
console.log(selectedText);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="TopicID" multiple="true">
<option id="1">ABC</option>
<option id="2">XYZ</option>
<option id="3">PQR</option>
</select>

Basic java script to get combobox

I am just starting out with some java script in an asp.net mvc web site.
I current have a form which I am working on.
The first field which the user is prompted with is a combobox / select (in html)
here is the code for it:
<select name="select">
#foreach (var item in Model.networks)
{
<option value="">#Html.DisplayFor(modelItem => item.name)</option>
}
</select>
Now my next field depends on the option which they chose from the combo box.
How can I populate the next field based on the option they chose in the combo box?
So when the user navigates to the page they will ave a combo box populated with all the options. Below that will be empty fields. When the user selects a option in the combo box I want it to then populate the empty fields with the corresponding data from the option which was chosen.
How do I go about doing this?
Please give the newby answer as in the method in which it will be done. I am assuming that I will be using java script for it?
Although I cannot understand your question in detail, I hope I can help you.
HTML
If you have a select element that looks like this:
<select id=dropdown>
<option value="1">test1</option>
<option value="2" selected="selected">test2</option>
<option value="3">test3</option>
</select>
Plain Javascript solution
Running this code:
var element = document.getElementByID('dropdown');
var current = e.options[e.selectedIndex].value;
Would make current be 2. If what you actually want is test2, then do this:
var e = document.getElementById('dropdown');
var strUser = e.options[e.selectedIndex].text;
Which would make current be test2
Put the onChange="getSelectedValue" attribute of the select element and then use the following javascript.
<script>
function getSelectedValue(sel)
{
txtToFill.Text(sel.options[sel.selectedIndex].text);
}
</SCRIPT>
If I understand your question correctly you want to react to a combo box value changing and display different content in your page.
If that is the case what you need to know is
how to handle the change event in the select (drop down)
populate empty fields
Here's how you can register and handle the change event in the dropdown:
$("select[name='select']").on("change", function(){
$('#input1').val("What you want in the input goes here");
});
Here's a fiddle that demonstrates this.

AngularJS selecting multiple options

So, What I'm trying to do is fairly simple with vanilla JS, but I'm using AngularJS and I would like to know how to do it the best way within the framework. I want to update the selected options in a multiple select box. I do not want to add or remove any of the options. Here is what my HTML looks like:
<select multiple>
<option value="1">Blue</option>
<option value="2">Green</option>
<option value="3">Yellow</option>
<option value="4">Red</option>
</select>
Using the following array, I'd like to programmatically select/deselect options from this list:
[{id:1, name:"Blue"},{id:4, name:"Red"}]
When I set this array in the scope, I want the select box to deselect anything that is not Blue or Red and select Blue and Red. The standard response that I've seen on the Google Groups is to use ng-repeat. However, I can't recreate the list every time because the list of selected values is incomplete. As far as I can tell, AngularJS has no mechanism for this, and I'm at a loss as to how I would do this without resorting to using jQuery.
ngModel is pretty awesome! If you specify the indexes as a model selectedValues
<select multiple ng-model="selectedValues">
built from your list (selected) in a $watch
$scope.$watch('selected', function(nowSelected){
// reset to nothing, could use `splice` to preserve non-angular references
$scope.selectedValues = [];
if( ! nowSelected ){
// sometimes selected is null or undefined
return;
}
// here's the magic
angular.forEach(nowSelected, function(val){
$scope.selectedValues.push( val.id.toString() );
});
});
ngModel will automatically select them for you.
Note that this data binding is one-way (selected to UI). If you're wanting to use the <select> UI to build your list, I'd suggest refactoring the data (or using another $watch but those can be expensive).
Yes, selectedValues needs to contain strings, not numbers. (At least it did for me :)
Full example at http://jsfiddle.net/JB3Un/

Is there a way to set `selected` flag instead of val() for dropdowns?

The select values are confusing me. When the user edits a row in my app I clone a tag with jquery (called empty-X) and put it on a modal window so that the user can edit the values. At the same time I get a json object (data) from server and fill in the current fields on the modal window as it stands in the database :
empty_X.find('#id_deals-1-currency').val(data[0].fields['currency']);
Now when the modal shows, the user can see how the correct currency is selected in the dropdown.
Yet when I check the HTML for this element with Firebug, I get a different picture, nothing seems selected.
<select id="id_deals-1-currency" name="deals-1-currency">
<option selected="selected" value="">---------</option>
<option value="1">USD - $</option>
<option value="2">EUR - €</option>
<option value="3">GBP - £</option>
</select>
And yet when I send the form to the server, there are no validation errors and the currency is the same value as it was previously set through val(). Life is good.
While this works by itself, there is a problem. What if the user wants to get back to the edit mode and verify the currency once more before saving it?
In this case I can't load the values from the database any more. His previous local changes matter now. I have to clone the current record with currency inside back in the modal window, so the user can see what he had changed previously and verify it. The problem is now the user doesn't see the currency he had changed in the previous step. In fact he would see an empty dropdown instead.
What are my options here? Is there a way to set the selected flag to the actual selection rather than using val()?
When cloning a <select>, the option with the 'selected' attribute becomes the current option in the cloned object - instead of the actual current object (as per value attribute).
To counter this, you can find the currently selected option from the value returned by val() and then apply the selected attribute to it prior to cloning it. This way you wont need to set the value after cloning.
Demo: http://jsfiddle.net/DqADq/
Code: (.x1 is the <select>)
// simple cloning
$('.x1:first').clone().appendTo('.out');
// setting selected attr before cloning
var v = $('.x1:first').val();
$('.x1:first option').removeAttr('selected'); // remove 'selected' from all options
$('.x1:first option').each(function() {
if($(this).attr('value') == v) {
$(this).attr('selected', true); // apply 'selected' to current option
}
});
$('.x1:first').clone().appendTo('.out');

Categories

Resources