"Required" validation doesn't work in <select> with default value - angularjs

I have a required <select> field:
<select name="service_id" class="Sitedropdown" style="width: 220px;"
ng-model="ServiceID"
ng-options="service.ServiceID as service.ServiceName for service in services"
required>
<option value="">Select Service</option>
</select>
When it is empty, the form should display a "Select service" error message. Here's a working plunker.
It works fine when you intentionally selects the empty option. But when you reload the page, the service_id is empty by default and there is no validation. How to make AngularJS validate the default value?

Your code:
ng-show="myForm.service_id.$dirty && myForm.service_id.$invalid"
This means - if value is dirty (was changed) and is invalid. Remove first and you'll get what you want.

Validation checks are only run after the value bound to ng-model is changed at least once, or when the user attempts to submit the form. If that was not the case, all the required fields of a form would be shown with error right after page loading, which would be a pretty undesirable behavior.
That's why you only see the error when selecting something else and then changing it back to the empty value.

Related

AngularJS: make the select work on click of dropdown, ngMessages issue

So I have a select box which populates some values into the dropdown using ng-options So I want to show the error messages as soon as the user click on the dropdown and focus out without making a selection.
JS Code
$scope.someMap = [{ name:"Abc", id:"a"},
{ name:"XYZ", id:"b"},
{ name:"FGH", id:"c"},
{ name:"TY", id:"d"}
];
HTML
<select name="inpName" ng-model="person.name" ng-options="i as i.name for i in someMap track by i.id" required>
<option value="" selected hidden/> </select>
<div ng-messages="form.inpName.$error" ng-if="form.inpName.$touched">
<div ng-message="required">Required field</div>
</div>
</div>
So it is working in a case where I add a blank option like option value="" selected hidden/> </select> and select some valid value and then select the blank option again, it gives error message as Required field.
But as you can see, the above selectbox will be blank once the page loads, so if use click on the dropdown and focus out without selecting or move to other field without selecting any value it should give error as Required field.
now if I try to iterate through the value of form.inpName.$error is never having any value and i cannot validate it using the above technique.
I have tried ng-show , ng-if , message expression may be am lacking some expertise.All of them works after selecting valid entry from dropdown and then moving back to blank option.
Solutions which would not work for me
Check model value:I do not want to go to model for these types of field and check if they are blank then show some error message, rather I want to iterate through the $error array and find the issue with the field
Make the default option selected when page loads- Cannot do it.
Add a field as selected one options : This will also not work because if the user did not touch the selection at all and filled all other fields the $error will not be populated for this select dropdown.
Any help would be much appreciated, really struck on this one.
As helped by #Ininiv in above post the code i posted works fine in plunker but not in my dev environment.
So based on some POJO/Entity out objects gets formatted with properties as null.So when i select and the option populates angular does not see as a change in the model, unless i select a value from dropdown and select a blank option from dropdown again. It gets activated.
But I wanted it to start working from the first touch itself, if left blank the error message should pop up.
To tackle this the ngModel needed to be set to null, when the dropdown the $error thing is activated and If i leave it blank and move to other field the error shows up.
So basically on the change of model only the ngMessages directive get activated which was not happening for dropdowns which were populating based on some object properties.

How to pre-select option from <select> tag in Angular with options from a different controller?

I'm using two controllers here. One, productComponentsController, handles a call to our database that pulls back an array of productComponent objects. The other, AddEditArticleController, controls the 'Create New / Edit Existing Article' page.
On my Add/Edit Article page, I want a <select> to populate with productComponents, and, if I am editing an existing Article, to be pre-selected with that Article's current productComponent.
Simple as this seems, I cannot make the field pre-select with the existing productComponent, though it does populate the <select> with them correctly. I've tried ngRepeat and ngOptions and both work for populating the dropdown, but neither works for pre-selecting the existing productComponentID from the array returned by the server.
My HTML, using ngOptions:
<!-- productComponentsController as pvm, AddEditArticleController as vm -->
<select id="componentBox"
ng-model="vm.selectedComponent"
placeholder="Select a Product Component"
ng-change="vm.changeProductID()"
class="form-control input-md"
ng-options="component.name for component in pvm.productComponents track by component.id"></select>
My HTML, using ngRepeat:
<!-- productComponentsController as pvm, AddEditArticleController as vm -->
<select id="componentBox"
ng-model="vm.selectedComponent"
placeholder="Select a Product Component"
ng-change="vm.changeProductID()"
class="form-control input-md">
<option value="{{component.id}}"
ng-repeat="component in pvm.productComponents"
ng-selected="vm.selectOption(component.id)"
ng-bind-html="component.name"></option>
</select>
<!-- vm.selectOption() returns true if the current option's ID equals the productComponentID of the current Article. Therefore this option would be selected. -->
In my AddEditArticleController, I set vm.selectedComponent equal to the productComponentID of the Article that was returned by the database, in the promise.then() of my call. While vm.selectedComponent does change, this doesn't do anything to the dropdown.
Also, in my generated HTML, I get the option: <option value="? number:47 ?"></option> (for an Article where the productComponentID is = 47). Apparently this happens as a result of the model being set to an unknown value but I don't know why the model would be set to anything other than an integer id.
Is this because my select is accessing multiple controllers, or am I missing something obvious here? Any help is greatly appreciated, let me know if more info is needed.
I believe you're looking for ng-init...
<!-- productComponentsController as pvm, AddEditArticleController as vm -->
<select id="componentBox"
class="form-control input-md"
placeholder="Select a Product Component"
ng-change="vm.changeProductID()"
ng-model="vm.selectedComponent"
ng-init="vm.selectedComponent=productComponentID"
ng-options="component as component.name for component in pvm.productComponents track by component.id"></select>
So it turns out that because the model has to be a string, I have to cast the vm.selectedOption to a string whenever it's changed (in this case, in the vm.selectOption function) using String(). This is using ngRepeat. ngInit seems to have no bearing on how my code works.
Boom, that's it, and my code works.

AngularJS changing the selected OPTION in a SELECT list based on a predefined value

I have a select list which is rendered via an ng-repeater and on change it fires the value of the selected option into a function this works as expected.
The issue I am now stuck on is if the page is loaded with a specific option requested how I ensure that select option is highlighted.
I have it so the GUID which is the value of the select is automatically fired to the function to get the page data for the selected item so that's working the issue is highlighting the selected item in the select list to show the user its related to that selection.
My code is below but you will see that I am binding it to ng-model="asCtrl.accSelected" which passed the GUID value. My assumption was that when a predefined GUID is requested I can set vm.accSelected to be equal to the GUID value and that should due to the 2 way binding show the selection on the select list but this doesn't seem to be the case.
<div data-ng-controller="tpAccStatusCtrl as asCtrl">
<select class="form-control" ng-model="asCtrl.accSelected" ng-change="asCtrl.retrieveAccount(asCtrl.accSelected)">
<option value="select" selected="selected">Select an Account</option>
<option ng-repeat="acc in asCtrl.accounts" value="{{acc.UniqueIdentifier}}">{{acc.AccountName}}</option>
</select>
</div>
I hope the above makes sense and someone can show me how to ensure the select list reflects the value set for vm.accSelected
Call the asCtrl.retrieveAccount(asCtrl.accSelected) function manually on page load. Ng-change will only trigger if the value is changed by the input, if I'm not mistaken.

Changing a dropdown value results in: Cannot read property entityState of undefined

I'm working on an existing AngularJS app where I need to add a new view. In the new view, there is a dropdown which triggers this error every time the value is changed. The dropdown loads all the data correctly. It's only when the value is changed that something goes wrong.
<select class="form-control form-controls input-sm" ng-model="vm.retailer.state" ng-options="state.code as state.name for state in vm.states track by state.code">
<option value="">-- Select a State --</option>
</select>
Here's the error:
TypeError: Cannot read property 'entityState' of undefined
Drilling into the first line on the stack trace, the error is happening here:
https://localhost:44398/bower_components/breezejs/breeze.debug.js:5284:20
It's inside this method:
function setNpValue(context, rawAccessorFn)
Here's the 'context' object. It all looks good:
context: Object
entityAspect: EntityAspect
newValue: "AL"
oldValue: null
parent: Retailer__Model
property: NavigationProperty
propertyName: "state"
__proto__: Object
Down inside the method is where the error is happening.
if (newValue != null) {
var newAspect = newValue.entityAspect;
if (entityManager) {
if (newAspect.entityState.isDetached()) {
if (!entityManager.isLoading) {
entityManager.attachEntity(newValue, EntityState.Added);
}
NewValue is accurately reflecting the new value I selected ("AL" in this case), so it is not null. However, on the next line down, newValue.entityAspect is undefined, so newAspect also ends up being undefined. As a result, when we get to this line:
newAspect.entityState.isDetached()
The error occurs.
I can post the entire controller for the view of where the dropdown exists, if that will help. But it seems like overkill. Looking for any help I can get. I'm pretty new to Angular.
EDIT / UPDATE:
I thought I had found the solution. As the solution to this question:
Dropdown in AngularJS has Correct Text, but Wrong Value
I had added "track by state.code" to the dropdown. In trying to troubleshoot THIS problem, I removed it. After a refresh, this error went away. WAHOO! But my joy was short lived. A short time later, the error came back. And now I'm back to square one.
Ok, I was able to solve this problem. Only it has created another. The problem here was in how I was building my dropdown:
<select class="form-control form-controls input-sm" ng-model="vm.retailer.state" ng-options="state.code as state.name for state in vm.states track by state.code">
<option value="">-- Select a State --</option>
</select>
I changed it to:
<select class="form-control form-controls input-sm" ng-model="vm.retailer.state" ng-options="state as state.name for state in vm.states">
<option value="">-- Select a State --</option>
</select>
And this error went away. But the thing is, I had added made this change to solve the problem I posted about here:
Dropdown in AngularJS has Correct Text, but Wrong Value
So now I'm back to trying to solve that issue.
I ran into this issue as well when I updated angular from 1.3.x to 1.4.x. When I converted back to angular 1.3.x, it went away. I assume there is something in the Breeze Angular Service that was broken by angular and has not been fixed by breeze yet.

Angular set error for required although option is selected

I have this code (there is $index because select's are inside ng repeater, I have more than one dynimally generated)
<select name="udaljenosti_{{$index}}" ng-model="attribute.Choices.Id" class="form-control" required>
<option value="" >--Choose--</option>
<option ng-repeat="choice in attribute.Choices" value="{{choice.Id}}" ng-selected="choice.IsSelected==true">
{{choice.Name}} </option>
</select>
There is IsSelected property on choice as you can see. If all choices have IsSelected==false, on submit I get error that some option is required because of required property on select, and when I choose some option on select and hit submit there is no error. Very good, so far. But, when some option is prepopulated from the database there is some strange behaviour. Everything seems good but when I click submit angular says there is error on select field. It says select is required but some option is already selected!!
EDIT: it seems name ang ng-model should much. How to accomplish this because I get error if I put uudaljenosti_{{$index}} inside ng-model?

Resources