Validate field count in angular form - angularjs

I have a form where a model contains an array of sub-models, like this:
<form name="form1">
<div ng-repeat="sub in model.submodels">
<input ng-model="sub.name" required>
<button ng-click="delSubmodel($index)">x</button>
</div>
<button ng-click="addSubmodel()">+</button>
<button ng-disabled="form1.$invalid" type="submit">Save</button>
</form>
How can I make form invalid when there are no input fields (or, in general, when the count of input fields is less than/greater than some value)
Update: Thanks for responses, I hope this can be done outside of controller.

Okay, I just got what you want to achieve, you will had to add a constraint to the form, which is the size of the subModel, so in your submit method:
Before doing anything
$scope.form1.$setValidity('size', model.subModels.length <= 0);
This will set the validity of the form to false in case your condition is false, or viceversa, you can also show a message to notify it to the user, adding this:
<form name="form1">
<div ng-repeat="sub in model.submodels">
<input ng-model="sub.name" required>
<button ng-click="delSubmodel($index)">x</button>
</div>
<input type="hidden" name="size" ng-model="model.subModels.length" />
<button ng-click="addSubmodel()">+</button>
<button ng-disabled="form1.$invalid" type="submit">Save</button>
You can check this example if you don't feel you didn't understood well my point, which is doing the same, just changing the validity for a single input.
Hope it helps you.

Related

Angular: Elegant way to toggle visibility of two related inputs

I have 2 related inputs in angular one is type number and the other is type text.
They both display the same value with the only difference being that the type text input displays the value of the type number input formatted for currency.
Only one of these is displayed at any given time. The behaviour I'd like is for the text input to be displayed initially and then on the click event the text input is hidden and the number input is shown. Similarly when the blur event happens on the number input the number input is hidden and the text input is shown.
The markup for this looks something like this:
<div>
<input type="number" ng-model="aValue" ng-blur="hideMeAndShowInputBelow">
<input type="text" ng-value="aValue | currency:'': '0'" ng-click="hideMeAndShowAndFocusInputAbove" readonly="readonly">
</div>
I know I could add extra properties to make this work but being relatively new to Angular this feels like the sort of thing that there is probably an elegant solution for.
Any help would be much appreciated.
You can assign a variable in ng-blur/ng-click and hide/show the inputs depending on the variable value.
<div>
<input type="number" ng-model="aValue" ng-show="showNumber" ng-blur="showNumber = false">
<input type="text" ng-value="aValue | currency:'': '0'" ng-show="!showNumber" ng-click="showNumber = true" readonly="readonly">
</div>
Check the plunker here:
https://plnkr.co/edit/yMFiXWuUF1R9BPGr2usT?p=preview
Alternatively, if this is a component you're going to use multiple times around your app, you could create a custom directive that achieves the same functionality, and thus avoid a lot of code duplication etc.
Try out something like this
<div ng-app="myApp" ng-controller="myCtrl">
<button class="btn btn-success" type="text" ng-model="firstName" ng-show="display" ng-click="display=!display"> BUTTON 1</button>
<br />
<button class="btn btn-warning" ng-click="display=!display" ng-model="lastName" ng-show="!display"> BUTTON 2
</button>
</div>
DEMO
Thanks for the suggestions. I followed the same approach but because I had some additional requirements (I wanted the value to be focussed when switching to the edit mode so the user can edit immediately without having to click the input again) I ended up writing a directive. It's here:
PLUNKER
But here is the markup.
<div class="mt-flight-input" ng-class="{'mt-dirty': value.newvalue != value.initial, 'mt-zero': value.newvalue == 0}">
<input type="number" class="mt-input" placeholder="0" ng-show="value.isAuthoring" ng-model="value.newvalue" ng-blur="checkValue('blur', value)" ng-focus="checkValue('focus', value)">
<input type="text" class="mt-input" placeholder="0" ng-show="!value.isAuthoring" ng-value="value.newvalue | currency:'': '0'| comma2dots" ng-click="showEditor($event, value)" ng-focus="showEditor($event, value)" readonly="readonly">
</div>

Put condition on ng-submit in multiple row item

I am working on Angualrjs.below is my code
<form name="myForm" ng-submit="OnClickSubmit())">
<div ng-repeat="ReadItem in SelectedItem" >
<label class="input">
<input type="text" id="txt_{{ReadItem.No}}" ng-model="ReadItem.Quantity" name="Quantity" required />
<div ng-show="myForm.Quantity.$dirty && myForm.Quantity.$error.required" class="note field-error">Required!</div>
<div ng-show="(myForm.Quantity.$dirty && ((5 < ReadItem.Quantity))" class="note field-error">Qty More.</div>
</label>
</div>
<button >order</button>
</form>
i wanted to perform validation on condition only when i click single button order.button is placed bottom of page.it's not added on every row.
1.my form is valid, i mean all field is not empty.
2.and quantity should not grater than 5.
please let me know how to achieve this functionality on multiple row item.
if any condition fail then OnClickSubmit() should not fired.
If I get your question right, ng-disabled and $invalid would be your bestfriend:
<button ng-disabled="myForm.$invalid" >Submit</button>
This will disable your button until all fields required is valid.

Validating nested form in angular

Having this ordinary (name attribute is requred by server) form with angular and can't figured out how to make validations work. What should i put into ng-show="TODO"
http://jsfiddle.net/Xk3VB/7/
<div ng-app>
<form ng-init="variants = [{duration:10, price:100}, {duration:30, price:200}]">
<div ng-repeat="variant in variants" ng-form="variant_form">
<div>
<label>Duration:</label>
<input name="variants[{{$index}}][duration]" ng-model="variant.duration" required />
<span ng-show="TODO">Duration required</span>
</div>
<div>
<label>Price:</label>
<input name="variants[{{$index}}][price]" ng-model="variant.price" />
<span ng-show="TODO">Price required</span>
</div>
</div>
</form>
</div>
ps: this is just piece of form, which is more complicated
Thanks
AngularJS relies on input names to expose validation errors.
Unfortunately, as of today it is not possible (without using a custom directive) to dynamically generate a name of an input. Indeed, checking input docs we can see that the name attribute accepts a string only.
Long story short you should rely on ng-form to validate dynamically created inputs. Something like :
<div ng-repeat="variant in variants" >
<ng-form name="innerForm">
<div>
<label>Duration:</label>
<input name="duration" ng-model="variant.duration" required />
<span ng-show="innerForm.duration.$error.required">Duration required</span>
</div>
<div>
<label>Price:</label>
<input name="price" ng-model="variant.price" required/>
<span ng-show="innerForm.price.$error.required">Price required</span>
</div>
</ng-form>
Working fiddle here
UPDATE : Base on your serverside requirement why not do something like that :
<input type="hidden" name="variants[{{$index}}][duration]" ng-model="variant.duration"/>
<input name="duration" ng-model="variant.duration" required />
The hidden input will be the one read by the server while the other one will be used to do the client side validation (later discarded by server). It s kind of an hack but should work.
PS : Be sure that your form is valid before actually submitting it. Can be done with ng-submit

angularjs ng-minlength validation is not working, form still being submitted

I am trying to submit the form on only successful validation.
validation is working for required but not working for ng-minlength
form input is invalid but form is still being submitted.
<form name="myForm" ng-submit="count = count + 1" ng-init="count=0" ng-app>
<div class="control-group" ng-class="{error: myForm.mobile.$invalid}">
<label class="control-label" for="mobile">Mobile</label>
<div class="controls">
<input type="text" name="mobile" placeholder="07XXXXXXXXX" ng-model="mobile" ng-minlength="11" required />
<span ng-show="myForm.mobile.$error.required" class="help-inline">Required</span>
<span ng-show="myForm.mobile.$error.minlength" class="help-inline">Mobile number should be minimum 11 character starting from 07</span>
</div>
</div>
<div class="control-group">
<div class="controls">
<input class="btn" type="submit" value ="submit" />
</div>
count: {{count}}<br />
<tt>myForm.$invalid = {{myForm.$invalid}}</tt><br/>
</div>
</form>
http://jsfiddle.net/pMMke/9/
what am I doing wrong.
I don't want to use submit button disable method.
This is what you are doing wrong: you are mixing two concepts, Angular validators and
HTML5 validators.
The required HTML5 validators, for instance, states that:
When present, it specifies that an input field must be filled out before submitting the form.
So, if you try to submit a form that has an input with this attribute, it will show a message explaining this to the user, and it will prevent the form from being sent. This is the behavior you want. Why isn't working for ng-minlength? Because ng-minlength is an Angular validator (you can tell because it begins with ng-), and it doesn't add any special behavior to the form. It simply set the input where it is located to invalid (and hence, the form), and let you decide what to do with it.
You have an option: you can use the pattern HTML5 validator, to specify the field requires at least 11 characters. It would like this:
<input type="text" pattern=".{11,}">
So when you submit a form containing this input, it will no be sent if the user has enter less than 11 characters.
But since we are it, and you are already using the pattern validator, you could use the regular expression in its full potential, and define something like:
<input type="text" pattern="07[0-9]{9}" />
Which will only admit values of 11 characters, that start by "07" and that contains only digits. I have modified your fiddle to show you how it would work: http://jsfiddle.net/helara/w35SQ/
I mistakenly used ngMaxlength="12" ngMinlength="6" instead of ng-minlength="6" ng-maxlength="12", it's working fine now.
Both ng-minlength & mg-maxlength works in AngularJS.
I've tested this in AngularJS version 1.3.
Make sure to use novalidate with <form> to disable browser's native validation.
This should work:
To enter mobile number
ng-show="myForm.mobile.$touched && myForm.mobile.$error.required"
For minimum length
ng-show="myForm.mobile.$touched && myForm.mobile.$error.minlength"
For maximum length
ng-show="myForm.mobile.$touched && myForm.mobile.$error.maxlength"
This work for me guys
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input ng-minlength="11" class="mdl-textfield__input" type="text" name="cpf" id="cpf" ng-model="avaliacao.cpf" ng-required="true" ng-pattern="/^\d+$/">
<label class="mdl-textfield__label" for="cpf">CPF *</label>
</div>
<p style="color: #d50000;" ng-show="myForm.cpf.$error.required && myForm.cpf.$dirty">Field Required</p>
<p style="color: #d50000;" ng-show="myForm.cpf.$error.pattern">Only numbers</p>
<p style="color: #d50000;" ng-show="myForm.cpf.$error.minlength">Min 11 Chars</p>
I'm facing the same issue, and I think you can only disable the button or ignore the entered value by yourself. You can also check the $valid property in your controller and ignore the value... It is not so nice, but I found no other way.

Angular JS Forms submit not sending model data

In the following example, message is undefined when I display it in the controller after the event is fired. Why?
<form>
<input type="text" ng-model="message.Title" />
<textarea ng-model="message.Content"></textarea>
<input type="submit" value="Send Message" ng-click="sendMessage(message)" />
</form>
Controller:
$scope.sendMessage = function(message) {
console.log(message);
}
My code seems identical to the documentation here except my controller manages the entire "page" not just the form.
Wow nevermind, apparently when you submit with blank values it doesn't even create the object.
I see you've found your problem, but I'd like to propose a solution to prevent your problem anyway:
<form name="messageForm" ng-submit="sendMessage(message)">
<input type="text" ng-model="message.Title" required/>
<span ng-show="messageForm.title.$error.required && messageForm.title.$dirty">required</span><br/>
<textarea ng-model="message.Content"></textarea>
<input type="submit" value="Send Message" ng-disabled="messageForm.$invalid" />
</form>
The above will make the Title required, display an error message, and disable your submit button if the form isn't valid.

Resources