Angular2 applies ng-valid class to field when required attribute is conditional and value is still empty - class

I'm using angular 2.3.1 and I have the following html element in a component template:
<input class="form-control" type="text" id="password" name="password"
placeholder="Password" [attr.required]="requirePasswd ? true : null"
[(ngModel)]="password">
If this is a new user (id is empty) then I want to require the password. If not a new user, the password is optional.
The conditional attribute is working but when used conditionally, the ng-valid class is applied even though the field still has no value.
If I hard code the required attribute, angular2 appropriately sets the class to ng-invalid, but when I make it conditional and requirePass is true, this element always has the ng-valid class even when it's still invalid.

Check out the Angular 2 source. You'll see that required is actually a Directive, so you'll need to use that syntax to setup your binding here.
It also takes a value, it doesn't just have to be present, so instead of passing in null you can just pass in true/false.
[required]="requirePasswd"

Related

Vuejs - setting the value of a textbox. (in laravel)

I am trying to set the value of a textbox with vuejs
#{{ message }} works in the body or in a tag.
this does not
<input type="text" name="column_name" v-model="reverseMessage" value="{{message}}">
Neither does.
<input type="text" name="column_name" v-model="reverseMessage" value="#{{message}}">
The problem is that you are trying to bind input value multiple variables. Both to reverseMessage (using v-model) and to value (using interpolation).
Please remove value="{{message}}" and just set reverseMessage variable - this should update the input view.
<input type="text" name="column_name" v-model="reverseMessage"/>
and then
this.reverseMessage = "my new input value"
You cannot bind input to many variables in the template itself. Use watchers or computed properties if you really need this.

Unable to keep the static data for the input type fields in angular material

How to make a default static value for input in material design?
<input type="text" value="xyz" />
but in material design angular I am unable to keep the static value like value="xyz
<md-input-container>
<label>Start date</label>
<input ng-model="agg.startDate" value="xyz">
</md-input-container>"
value xyz is not affected in this case.
In your controller create a variable named agg.startDate using the $scope variable, like following code to set the value of input field
$scope.agg = {startDate: 'xyz'};
check this fiddle link

angularjs form can not refer to input control when input name is array

I encounter a problem when testing form validation with angularjs
According to angularjs form guide,
an input control that has the ngModel directive holds an instance of NgModelController. Such a control instance can be published as a property of the form instance using the name attribute on the input control.
I created test code at plunker, it all works fine untill I change the input name from
<input type="number" name="age" ng-model="user.age" max="100" required>
<p>{{form1.age.$error}}</p>
to
<input type="number" name="user[age]" ng-model="user.age" max="100" required>
<p>{{form1.user[age].$error}}</p>
Does this mean angular can not recognize array syntax in form input?
The problem for me is I want to keep the normal form submission flow and only use angular for form validation, so I need to keep form input as array to work with the backend form handling
It has nothing to do with Angular. It is a syntactic JS error.
If you want to reference a property named user[age], you should do it like this:
form1['user[age]'].$error
form1.user[age] is incorrectly interpreted as (form1.user)[age]

How can I automatically add labels to input fields?

I'm working on a bigger project with AngularJS. Therefore, I want to make the work for a single form as easy as possible. As we're also using bootstrap, the code for a single input field in a form is quite verbose, maybe like
<div class="control-group">
<label class="control-label" for="inputEmail">Email</label>
<div class="controls">
<input type="text" id="inputEmail" placeholder="Email">
</div>
</div>
If I could write a single tag like
<custom-input
label="Email"
name="inputEmail"
placeholder="Email"
type="text"
... >
</custom-input>
instead, this would help to keep the code clean and the work simple.
To achive this, I'm working on a custom AngularJS directive. My directive currently uses a template similar to the bootstrap example from above, automatically assigning the label to the input-tag. Also, the directive's compiler function moves all attributes from the custom-input tag to the real input-tag in order to make it easy to customize the custom-input tag.
app.directive('customInput', function() {
return {
require: 'ngModel',
restrict: 'E',
template: '<div>' +
'<label for="{{ name }}">the label</label>' +
'<input id="{{ name }}" ng-model="ngModel" />' +
'</div>',
scope: {
ngModel: '=',
name: '#name',
},
replace: true,
compile: function (tElement, tAttrs, transclude) {
var tInput = tElement.find('input');
// Move the attributed given to 'custom-input'
// to the real input field
angular.forEach(tAttrs, function(value, key) {
if (key.charAt(0) == '$')
return;
tInput.attr(key, value);
tInput.parent().removeAttr(key);
});
return;
},
};
});
On Stack Overflow, there are many questions regarding the creation of custom input fields, but they are concerned with the data binding, custom formatting or binding to ng-repeat.
My approach however has a different issue: while the data binding works correctly, Angular's integrated form validation module get confused when the input field is 'required'. For some reason, validation doesn't recognize the new input field and instead keeps the form invalid because of some dead reference, which has an empty value. Please see the minimal example.
Where does the dead reference come from? How can I update the validation-module's references? Is there a better way to achieve my overall goal?
As a boolean attribute, there is a corresponding required property that is still true on your div even if the attribute is moved.
The required attribute isn't getting moved, it must be getting skipped because there is no value. I don't know how to even add it to an element using javascript without a value, but using the form required="required" fixes that
Using transclude=true will use a copy of your element after the compile phase when you moved attributes, I think this keeps the required property from being set
You have to assign a higher priority for some reason, maybe because of ng-model, which is not removed from your div because the name in tattrs is ngModel (although removing from the div doesn't remove the need for priority)
http://plnkr.co/edit/5bg8ewYSAr2ka9rH1pfE?p=preview
All I did was change the required attribute to be required="required" and add these two lines to the directive declaration:
transclude: true,
priority: 10,
I put ng-transclude on the template label by the way so the contents of your element will go in the label and you don't have to have an attribute for that.

Play 2.0 Nested forms: generate <input id="email"> instead of <input id="user_email">

Posted this to Play user group; I account for the sole view, so hoping to get a view, or perhaps even an answer ;-)
Nested forms are great, but there's one glitch that adds boilerplate to either javascript or scala templates.
For example, given:
#inputText(field = _form("user.email"),
'_label-> "Email Address*",
'class-> "required email",
'placeholder-> "jdoe#gmail.com"
)
the generated input field is something like:
<input id="user_email" name="user.email" ...>
Now, when you want to validate the email address client-side you then have to reference DOM id: $('#user_email')
Where $('#email') would be more natural.
I know I can set the id attrib manually in the template but would prefer to, by default, have the nested name (user in this case) stripped out from the id attrib.
Looking in github views helper directory, I am not finding where I can get access to the generated id (i.e. which file I need to overload and how).
Anyone know how to pull this off and/or have a better approach?
Here is where the field's ID is auto-generated:
https://github.com/playframework/Play20/blob/master/framework/src/play/src/main/scala/play/api/data/Form.scala#L274
There's not really any way you can override that behaviour, but you could write your own #inputText helper that strips the "user_" part from the ID when generating the HTML.
Basically copy-paste the default helper and replace
<input type="text" id="#id" ...
with your own code, e.g.
<input type="text" id="#processFieldId(id)" ...
or (untested!):
<input type="text" id="#(id.split('_').last)" ...
Then just import your custom helper in your template, and use it just like you would use #inputText.