AngularJS: Limit selections from dropdown list (using angularMultipleSelect) - javascript

I'm stuck on this issue: I'm trying to limit the number of selections a user can make from an available dropdown selection list. The list is drawn from a database, so its not a hard-coded option list. I'm currently using angularMultipleSelect, its works fine expect for this requirement.
If the user exceeds the maximum selections, I want to set the field to invalid, so that the user cannot save the form. The user should then remove one or more of the selections, until the valid selections are made, then the field should reset to valid. I've tried using:
after-select-item (a directive available with angularMultipleSelect)
ng-change
custom validation directive
None of these work. I can get ng-change & custom validation directive to work on other input fields in the same form, but not on the 'multiple-autocomplete' tag. Nothing is triggered when the user makes selections from the dropdown list.
Here is a simple sample of the code used with after-select-item method. I'm trying to limit the user to 3 or less selections from the available options in the 'cats' array.
HTML:
<multiple-autocomplete
ng-model="selectedCats"
name="selectedCats"
object-property="name"
after-select-item="afterSelectItem"
required
suggestions-arr="cats">
</multiple-autocomplete>
Controller.js:
$scope.afterSelectItem = function(selectedCats) {
var catLength = $scope.selectedCats.length;
var valid = (catLength <= 3);
$scope.myStoryForm.selectedCats.$setValidity("maxLength", valid);
};
Again, nothing gets triggered in this controller when selections are been made (checked at console).
Is there something I'm not doing right, or is there another approach I could use to meet this requirement?
Thanks.

You could try using $watch to watch for changes in your model.
E.g.
$scope.$watch("selectedCats", function (newValue, oldValue) {
var catLength = newValue.length;
var valid = (catLength <= 3);
$scope.myStoryForm.selectedCats.$setValidity("maxLength", valid);
});
This gets triggered every time that your "selectedCats" value changes as well as the first time that you initialise the value.

Related

Click all checkboxes on a webpage with HTML script (quickbooks/Safar)

So I created the following script to select all check boxes on a page
(function(d) {
var input = d.querySelectorAll('input[type="checkbox"]');
var i = input.length;
while (i--) {
input[i].checked = true;
}
})(this.document);
It does work to do that, however when trying it in Quickbooks while it does select all the boxes, the website does not register it as actually being selected (the total cost at the bottom remains the same, its like it superficially checks the boxes, visually only with no actual register). Any help would be great.
EDIT: Maybe simulating a click instead of changing the box values?
The only thing that changes when physically selecting a box is the value posted below changes to true from false
You should do :
input[i].setAttribute("checked", "");
The checked attribute is a boolean attribute, so the standard way to add it to an element is to pass an empty string for value.
https://developer.mozilla.org/fr/docs/Web/API/Element/setAttribute#Exemple

<ng-select > after on changes formGroup control value still null,if searchTerm provided programmatically

I have requirement to set searchTerm value Programmatically(using Virtual keypad) and search the dropdown should show searchterm based options.
where form control is updateOn:'blur'.
But here i am facing issue like form control is not getting updated after selecting dropdown option based on searchTerm provided by virtual input key(in example stackblitz red color text control value is null).
Steps:
1.press virtual key pad button
2.select any option
3.now check red color text value:
Thanks.
It is getting updated, but you are using before it is updated. Even if you open the <ng-select> yourself, it will show different values in black and red.
If you can, I'd suggest for you to use change.id instead:
this.afterChangesFormControlValue = change.id;
But if you can't... if you wrap it inside a setTimeout(), even with a 0 delay, it will start working, since the setTimeout will be triggered only after the update is done:
setTimeout(() => {
console.log('on select option after given search term from virtual keyboar')
console.log("change:",change)
console.log("form control value:",this.form.controls.example.value)
this.afterChangesFormControlValue=this.form.controls.example.value;
}, 0);
Both should produce the same results - they did when I tested in your Stackblitz, but setTimeout is a bit unsightly.

Select value during onblur event when using typeahead

I have a simple typeahead for a list of currencies. When I start typing and I select the desired value (or hit TAB on that), the desired value is selected - until this point everything works as desired.
However, if I type the entire word and click outside the input instead of selecting the value (onblur event), then even if the value inside my input matches the filter value, the selected scope variable doesn't update, so my input is invalid. What I'm trying to do is to overwrite the selected value during onblur event.
Example: If I type EUR without hitting TAB or selecting the EUR value from the typeahead dropdown and then click outside the input, the EUR text stays inside the input, but selected value is undefined. I want the selected value to hold EUR instead of undefined. I used $viewValue to send the input value during onblur event.
The HTML:
<input type="text" ng-model="selected" typeahead-editable="false" typeahead="currency for currency in currencies | filter:$viewValue" ng-blur="selectCurrency($viewValue)" />
<div>Selected: {{selected}}</div>
The JavaScipt:
angular.module('myApp', ['ui.bootstrap'])
.controller("mainCtrl", function ($scope) {
$scope.selected = '';
$scope.currencies = ['EUR', 'GBP', 'USD'];
$scope.selectCurrency = function(test) {
console.log(test); //outputs undefined instead of EUR
//if (checkIfCurrencyExists(test, $scope.currencies)) { - will do the checks later
$scope.selected = test;
//}
};
});
In the JsFiddle below you can see the same scenario, except it has US states instead of currencies. Try to type in Alabama then left click outside the input (don't TAB and don't select the state), you'll see that the selected scope variable stays empty
JsFiddle link here.
Found another solution - setting both typeahead-select-on-exact and typeahead-select-on-blur attributes to true:
<input typeahead-select-on-exact="true" typeahead-select-on-blur="true" uib-typeahead=...
Typeahead-select-on-exact makes the exactly matching item automatically highlighted in the list, and typeahead-select-on-blur makes the higlighted item selected on blur.
If you want to select the first result from the typeahead list on blur, then you can set typeahead-select-on-blur="true" in your input field as given in the doc.
typeahead-select-on-blur (Default: false) - On blur, select the
currently highlighted match.
Found an answer myself at the time, but forgot to answer my question here.
Added this to the directive:
data-ng-blur="blur($event)"
And this is the function:
$scope.blur = function(e) {
var inputCurrency = e.target.value.toUpperCase();
angular.forEach($scope.currencies, function(currency) {
if (currency === inputCurrency) {
$scope.field = currency;
}
});
};
I spend some time searching for similar question and made a lot of testing untill I got it working. I can see that in answers there is a solution but I try to summarize it so it could be a bit more clear.
In typeahead part include:
<input type="text" ng-model="selected" typeahead-editable="false" typeahead="currency for currency in currencies | filter:$viewValue" ng-blur="checkSelectedValue()" typeahead-select-on-blur="true" />
First part includes validation function of your scope value (you don't need to pass the value as it's the $scope.selected and you can use it in your controller): ng-blur="checkSelectedValue()".
Thus include in your controller:
$scope.checkSelectedValue = function() {
if (code that check if $scope.selected in range of allowed values) {
$scope.inputValid=true; //you can use this scope or write code that run when selected a correct value
} else {
$scope.inputValid=false;
}};
Second part: typeahead-select-on-blur="true"// it's necessary since it first will make $scope.selected=selected value from dropdown (complete word) but also a bit weird, but important to know that after typeahead will selected your value it will run ng-blur= "checkSelectedValue()" directive in the end so there it will always check for validation and will set your $scope.inputValid=true or false depending on $scope.selected value.

angular forms validation issues when using plugins

I have an Single Page Application build using Angular and i am having some issues with the form.
Form is using a check box a drop down and two text boxes.
first text box (Name) has no validation.
check-Box is using a third party plugin called "iCheck".
Drop down is using a plugin called "bootstrap-select".
Validation is using a library called "Jquery Validation Engine".
The plunker is setup here
The expected behavior is. In simple words the text box and drop are required if check-box is checked.
1) On Page load because form is not dirty (none of the controls were supplied any value) if i click the save button it should hit the save function because there were no validation on the controls, hence there should be no validation message prompt on the screen.
2) If i click the check box. the drop down and the text box below becomes required. it means that both drop down and text box has conditional validation (feature of Jquery Validation Engine) which is already setup and working .
so now if i click Save, it should not hit the save function and display the validation prompt.
3) it should keep on restricting the function access and display the validation error prompt unless form controls are valid i.e. some value is selected in drop-down and text boxed is filled.
4) and if i un-check, validation described in point number 3 goes away.
But whats happening is:
a) On page load if i click the save button it does not hit the save function.
b) If i click the check box it still does not hit the save function and validation error prompts are display on both drop down and text-box which is fine thats how it should behave.
c) When is fill the required text box it makes the form ng-valid and it hit the
save function how ever the drop is still in ng-invalid.
d) Even if i select some thing from the drop down the validation prompt remains on the drop down and it still hits the save functions.
e) (Not that much worried about this issue) lastly want to setup a custom value in the drop down that should act as default e.g. "--Select One--" and if the default is selected it should be considered as nothing is selected and it should be considered as invalid when validation is active.
all of this code is in dashboard.html and dashboard.js since i am using plugins so i needed directives to work with them properly. Directives for check-box, Select and Validation are in dashboard.js under the controller code.
Controller code is setup like this.
(function () {
'use strict';
var controllerId = 'dashboard';
angular.module('app').controller(controllerId, ['$scope', dashboard]);
function dashboard($scope) {
var vm = this;
vm.title = 'Dashboard2';
vm.CurrCustomer = {};
vm.CurrCustomer.Name = ""; //first text box
vm.CurrCustomer.Logic = false;
vm.CurrCustomer.SetThreshold = false;
vm.CurrCustomer.Threshold;
vm.saveChanges = function () {
alert('function called');
var NewCustomer = vm.CurrCustomer;
// submit NewCustomer to DB.
};
$scope.toggleSelection = function () {
vm.CurrCustomer.SetThreshold = !vm.CurrCustomer.SetThreshold;
};
}})();

How to create dynamic select field with blank option and unfiltered state

I need to create a dynamic select field in Rails 3.2, where the options available in the second fields (states) depends on the value of the first (country). I've referred to the revised version of this Railscast, and am using the following code:
jQuery ->
$('#person_state_id').parent().hide()
states = $('#person_state_id').html()
$('#person_country_id').change ->
country = $('#person_country_id :selected').text()
escaped_country = country.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/#])/g, '\\$1')
options = $(states).filter("optgroup[label='#{escaped_country}']").html()
if options
$('#person_state_id').html(options)
$('#person_state_id').parent().show()
else
$('#person_state_id').empty()
$('#person_state_id').parent().hide()
I need to make two changes to this code, which I think should be pretty straightforward for someone with stronger javascript skills than I have.
In the filtered list, I need to include a blank option. Currently selecting a country results in the first state state in the filetred list being selected. I need to leave the prompt "please select". How can I do this?
EDIT
SMathew's suggestions helped here. I'm using $('#person_state_id').html(options).prepend('<option></option>') which, together with a prompt attribute on the html tag, acheives the required result.
If no country is selected (ie the else statement) person_state_id should contain a complete, unfiltered list of all states. I've tried:
else
$('#person_state_id').html(states)
But this is not behaving as expected. I'm having these issues.
If I select a country that has associated state records, #person_state_id options are correctly filtered (and with smathews suggestion, a prompt is included).
If I select a country with no associated state records, #person_state_id contains all states, a blank option in the markup, but the first state option is selected by default. (It should be empty, with a blank option selected by default and a prompt displayed).
If I clear the selection in #person_country_id, #person_state_id contains an unfiltered list of all states (correct), and an empty option in the markup (correct) but the first state record is selected by default (should be a prompt).
How can I resolve these issues?
Thanks
Try
...
if (options) {
$('#person_state_id').html(options).prepend('<option>Please select</option>').parent().show()
} else {
$('#person_state_id').html(states).prepend('<option>Please select a state</option>').parent().show()
}
To deal with my second problem, I added the following coffeescript
jQuery ->
resetCountry = ->
$('#person_state_id').select2 "val", "0"
$('#person_country_id').bind("change", resetCountry);
This, coupled with smathew's answer, seems to be working
(I'm using select2 to format my select fields. You'll need a different approach to set the value if not using select2)

Categories

Resources