angular form how to show changed save button text? - angularjs

I use angular 1 form to show changed save button text.
The button text should be the follow:
(disabled) save - when initial
(enable) save - when edited or re-edit after saved
(enable) saved - click save button
How can I use a simple method to resolve it?
sample JSFiddle here or the follow code
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function($scope) {
$scope.buttonText = 'save';
$scope.save = function (myForm) {
myForm.$setPristine();
$scope.buttonText = 'saved';
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="MyCtrl">
<form name="myForm">
<input type="text" ng-model="text1" name="text1">
<input type="text" ng-model="text2" name="text2">
<button ng-click="save(myForm)" ng-disabled="myForm.$pristine">
{{buttonText}}
</button>
</form>
</div>
</body>

Change your button markup to this:
<button ng-click="save(myForm)" ng-disabled="myForm.$pristine">
{{myForm.$pristine?buttonText:'save'}}
</button>
Working fiddle

You could attach a watch to the form model object and set the text back to 'Save'?
Asides from that you already have it with the initial value and setting to Saved when button is clicked
$scope.$watch("myFormData", function(){
// text is 'Save'
}, true);
For the following to work, put all your form data in an object variable.
I.e.
myFormData = {};
myFormData.text1 = "hi"
So you can change the ng-model binding to a viewmodel - which is good practice anyway!

Related

Angular, how to conditionally style a required field?

I do not want to display validation of my form until the submit button is pressed. When the button is pressed the form should be submitted if valid, and if not submitted invalid fields should become highlighted in red.
For legacy reasons, I am importing a css file which defines input:invalid with a red background, as a result any input field marked as required will always display as red.
I attempt to make this work in the below fiddle by conditionally setting ng-required. Which somewhat works, with the exception that the first time the submit button is clicked the form $valid evaluates to true.
How can I conditionally set ng-required such that my field is only styled after the submit button has been clicked, and the form $valid consistently evaluates correctly based on the field being empty/non-empty?
https://jsfiddle.net/dk89dhp2/19/
You have two issues. The first is simply a typo.
this:
ng-required="myForm.showErrors"
should be:
ng-required="showErrors"
to match what's in the model.
Once you fix this, you will notice it almost works except the dialog says the form is valid when it should not. To give the digest cycle a chance to run, you can wrap whatever you need to do in a $timeout. (Could also use a proxy function that sets the value of showErrors then calls the submit function from a $timeout)
$scope.myForm.submit = function() {
$scope.showErrors = true;
$timeout(function() {
alert("form validity is: " + $scope.myFormNg.$valid);
});
};
updated jsfiddle
This works:
https://jsfiddle.net/q6ur26mt/
I just changed the ng-required value to true.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
<body ng-app="myapp">
<div ng-controller="MyController" >
<form name="myFormNg">
<input type="text" ng-class="myForm.getCssClassForField(myFormNg.id)" ng-required="true"
name="id" ng-model="myForm.id" />
ID
<br/><br/>
<button type="button" ng-click="myForm.submit()">submit</button>
</form>
</div>
</body>
<script>
angular.module("myapp", [])
.controller("MyController", function($scope) {
$scope.myForm = {};
$scope.showErrors = false;
$scope.myForm.submit = function() {
$scope.showErrors = true;
alert("form validity is: " + $scope.myFormNg.$valid);
};
$scope.myForm.getCssClassForField = function(field) {
return field.$invalid && $scope.showErrors ? 'invalid' : '';
};
});
</script>

AngularJS - unchanged data passed by ng-model is interpreted as undefined instead of the value

I'm using Angular to generate some inputs and populate them with data using ng-repeat. I also want to bind the data inside the input to a save changes button which takes parameters provided by ng-model directives. save changes button prints the passed arguments using the built-in JS arguments object. For some reason, unless I change the text inside the input box, the output is [undefined, undefined]. Once I change the text inside the input boxes, the correct output is printed. Why is that?
JSfiddle code.
HTML:
<div ng-app="myApp" ng-controller="MainCtrl">
<p ng-repeat = "man in men">
<label>name</label><input type="text" ng-model="mname" ng-value="man.name"><br>
<label>status</label><input type="text" ng-model="mstatus" ng-value="man.status"><br>
<button ng-click="save(mname,mstatus)">
save changes
</button>
</p>
</div>
JS:
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope) {
$scope.men = [{
name: "jon snow",
status: "depands"
}, {
name: "rob stark",
status: "dead"
}];
$scope.save = function() {
console.log(arguments);
}
});
This is not recommended but for your specific requirement you can use ng-init to bind ng-value to your model
<p ng-repeat = "man in men">
<label>name</label><input type="text" ng-model="mname" ng-value="man.name" ng-init="mname = man.name"><br>
<label>status</label><input type="text" ng-model="mstatus" ng-value="man.status" ng-init="mstatus = man.status"><br>
<button ng-click="save(mname,mstatus)">
save changes
</button>
</p>
This wouldn't bind your changes to the original model.
Fiddle
ngModel doesn't update untill you use a key to change it, or set it from your controller. Because you are setting the field of the input using ngValue, it doesn't register to your ngModel untill you change it.
This problem is similar to how most datepickers don't work with ngModel, as they set the field with DOM-manipulation and NOT by inserting the value by "key".
You can easily fix this by using the following HTML instead:
<label>name</label><input type="text" ng-model="man.name"><br>
<label>status</label><input type="text" ng-model="man.status"><br>
I simply removed the ngValue and linked the ngModel to your "man".

Form object undefined when using Angularjs blockUI

I'm using Angularjs, version 1.5, and i have specified a form in my html as follows:
<div class="row" ng-show="showForm">
<form class="form-horizontal" name="myForm" novalidate role="form">
</form>
</div>
In the corresponding controller i have a function that resets the form and calls pristine:
$scope.myForm.$setPristine();
Until now everything works fine.
I then try to use blockUI (https://github.com/McNull/angular-block-ui)
by changing the above div to:
<div class="row" ng-show="showForm" block-ui="myBlock">
so the only addition is: block-ui="myBlock"
however, when the controller code runs i get:
TypeError: Cannot read property '$setPristine' of undefined
When debugging i see that the form object does not exist! When removing block-ui="myBlock", everything works fine again.
Any ideas?
Thanks in advance
Try something like these:
function MyCtrl($scope, $timeout, blockUI) {
$scope.form = {};
$scope.submit = function() {
var myBlockUI = blockUI.instances.get('myForm');
$scope.form.myForm.$setPristine();
myBlockUI.start();
$timeout(function() {
// Stop the block after some async operation.
myBlockUI.stop();
}, 3000);
};
}
and view:
<form name="form.myForm" novalidate ng-submit="submit()" block-ui="myForm">
<input type="text">
<button>
Submit
</button>
</form>
I have same trouble like you with undefined form on $scope, but found these trick with using additional object form on SO. Plunk here.

Reset form to pre validation state?

We are new to angular and we wanted to use angular validations with our forms. We are using async ajax calls with a kendo grid to get, create, edit and save data without any submit. I am having a hard time figuring out how to reset the validation state of the form when the user chooses to create a new record.
I made this small exaple, trying anything I could find in sof without any luck so far:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.4/angular-messages.min.js"></script>
<div ng-app="app">
<div ng-controller="ValidationController">
<form name="myForm" novalidate>
<label>
Name
<input name="nombre"
ng-model="field"
required />
</label>
<div ng-messages="myForm.$error">
<div ng-message="required" ng-if="myForm.nombre.$touched" ng-messages-include="myMessages">
</div>
</div>
<button type="button" ng-click="reset(myForm);" value="Reset">reset validation</button>
</form>
<script type="text/ng-template" id="myMessages">
<div ng-message="required">required field</div>
</script>
</div>
</div>
<script>
angular.module('app', ['ngMessages']).controller("ValidationController", function ($scope, $window) {
$scope.reset = function (form) {
form.$setPristine();
form.$setUntouched();
form.$setValidity();
form.nombre.$setPristine();
form.nombre.$setValidity();
form.nombre.$setUntouched();
}
});
</script>
Here is my fiddle:
https://jsfiddle.net/yh9q1a2j/
Update:
I think this better suits your needs. I've updated the fiddle
https://jsfiddle.net/n7qqn1x6/6/
In your reset method call $setPristine along with clearing the formData object.
$scope.formData = {};
$scope.myForm.$setPristine();
To get the error messages to be removed from the page once added I had to use ng-show instead of ng-if
<div ng-show="myForm.nombre.$error.required&&myForm.nombre.$dirty">required</div>

Validating repeating inputs inside an AngularJS form

I know this has been asked before, and have even found a well-upvoted answer here:
How to validate inputs dynamically created using ng-repeat, ng-show (angular)
But I can't get that solution to work. I've got an example here - annoyingly both jsFiddle and Plunkr seem to be down right now.
Here's the JS:
app.controller('DetailsCtrl', ['$scope', function($scope) {
$scope.loading = false;
$scope.formData = {
lines: [{
text: 'test.com'}]
};
$scope.addRow = function() {
$scope.formData.lines.push({text:null});
};
}]);
Here's the markup:
<body ng-controller="DetailsCtrl">
<div>
<form name="mainForm" novalidate class="form-vertical">
...some non-repeating inputs go in here...
<div data-ng-repeat="line in formData.lines" data-ng-form="lineForm">
<input type="text" name="myinput" data-ng-model="line.text" data-ng-required="true">
<span data-ng-show="mainForm.lineForm.myinput.$error.required">Error!</span>
</div>
New Line
</form>
</div>
</body>
You'll notice initially there is one text input with text in - great. Click the 'New Line' link. Because the new text input fails validation - BOTH text inputs get the warning span shown... I just want the one span relating to the one empty text input to show up.
As AngularJS relays on input names to expose validation errors, and you used the same name for all inputs, you faced with this effect.
So you can't generate input name dynamically, but instead you can use ng-form (see https://docs.angularjs.org/api/ng/directive/ngForm).
<form name="mainForm" novalidate class="form-vertical">...some non-repeating inputs go in here...
<div data-ng-repeat="line in formData.lines" data-ng-form="lineForm">
<input type="text" name="myinput" data-ng-model="line.text" data-ng-required="true">
<span data-ng-show="lineForm.myinput.$error.required">Error!</span>
</div> New Line
</form>
EDIT. Please note, access to error myinput.$error.required instead of lineForm.myinput.$error.required.
Please, checkout working fiddle http://jsfiddle.net/Y9g4q/7/.

Resources