AngularJS v1.5.5 Reset form not working for invalid input fields - angularjs

I have the code below (or see the fiddle) and I try to reset form and clear all input fields too for each form.
With AngularJS version 1.2.1 is working fine! but in my app I using version 1.5.5 because I have other libraries for separating the nested forms in <md-tab> tags using material framework who need this version.
The problem is when any field it's invalid then reset does not work as expected and these fields remain unchanged instead to be clear.
There is another way to clearing all fields (of nested form) when I click reset button ?
angular.module("main", [])
.controller("register", function($scope) {
$scope.data = {
A: {},
B: {}
};
$scope.reset = function(form) {
form.$setPristine();
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<body ng-app="main">
<div ng-controller="register" class="form">
<form name="form" novalidate role="form">
<div class="form">
<h1>TAB1 - Form A:</h1>
<ng-form name="A">
A1:
<input type="text" ng-model="data.A.A1" ng-minlength="4" ng-maxlength="15" />A2:
<input type="text" ng-model="data.A.A2" ng-minlength="4" ng-maxlength="15" />
<button type="button" ng-disabled="A.$pristine" ng-click="reset(A); data.A=null;">Reset</button>
<br/>
<strong>A.$pristine =</strong> {{A.$pristine}}
<strong>A.$valid =</strong> {{A.$valid}}
</ng-form>
</div>
<br/>
<br/>
<div class="form">
<h1>TAB2 - Form B:</h1>
<ng-form name="B">
B1:
<input type="text" ng-model="data.B.B1" ng-minlength="4" ng-maxlength="15" />B2
<input type="text" ng-model="data.B.B2" ng-minlength="4" ng-maxlength="15" />
<button type="button" ng-disabled="B.$pristine" ng-click="reset(B); data.B=null;">Reset</button>
<br/>
<strong>B.$pristine =</strong> {{B.$pristine}}
<strong>B.$valid =</strong> {{B.$valid}}
</ng-form>
</div>
</form>
<h1>data:</h1>
<pre>{{data | json}}</pre>
</div>
</body>

It's because ng-model binds to the A and B objects by reference in $scope.data. If you remove the $scope.data.A = null from your ng-click and reset the object without creating a new one, it works:
https://jsfiddle.net/utwf604r/15/
$scope.reset = function (form)
{
// don't change the reference to A
// $scope.data.A = {} wont work!!
angular.extend($scope.data, {A:{A1:'',A2:''}, B:{B1:'',B2:''}});
form.$setPristine();
};

Related

angular removes ng-model variable if ng-required is true

as in the title.. how to prevent such operations to happen? Here is a link to the official site, see the example. The variable user.name is bound to the first input userName and if the input is empty the object user.name is removed. How can I disable this functionality of angularjs?
Try ng-model-options="{allowInvalid: true}" to update the model even for invalid entries.
<input ng-model="user.name" required ng-model-options="{allowInvalid: true}">
You've got 2 option
remove required from input tag it allows you to send back empty string to your backend
var app = angular.module('app', []);
app.controller('MyCtrl', function($scope) {
$scope.params = {
user: "John"
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="MyCtrl">
<input name="userName" ng-model="params.user" />
<hr/>
<pre>{{params| json}}</pre>
</div>
Option two validate your form before you send it to backend.
var app = angular.module('app', []);
app.controller('MyCtrl', function($scope) {
$scope.user = {
name: "John"
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="MyCtrl">
<form name="someForm">
<input name="userName" ng-model="user.name" required name="userName" />
<span ng-show="someForm.userName.$error.required">User Name required</span>
<br/>{{user | json}}
<br/>
<button type="submit" ng-disabled="someForm.$invalid">Submit</button>
</form>
</div>

map bind with ng-model not updating data

I called REST service which gives me an Object contains a map.
Map in java looks like Map
Following is my js
$scope.marks = {};
//get data from rest
StudentService.query().$promise.then(function(data)
{
$scope.students = data;
for(var i=0;i<$scope.students.length;i++){
var obj = $scope.students[i];
//marks (key=studentName, value=mark in decimal)
$scope.marks[obj["studentName"]]=0.0;
}
following is my html
<div class="row" ng-repeat="(key,value) in marks">
<input type="text" class="form-control" ng-model="key" disabled>
{{marks[key]}} <!-- Here it is not updating value from above model-->
<input type="number" class="form-control" ng-model="value">
</div>
When I update value in textfield it is not update value displayed just below textfiled ie {{marks[key]}} is not showing updated value. Please correct me if wrong. Thank you :)
What you are passing to the ng-model is just a string, which is immutable. You need to define the ng-model like this:
<input type="number" class="form-control" ng-model="marks[key]">
angular.module('app', [])
.controller('Ctrl', function($scope) {
$scope.marks = {
mark1: 1,
mark2: 2,
mark3: 3
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="Ctrl">
<div class="row" ng-repeat="(key,value) in marks">
<input type="text" class="form-control" ng-model="key" disabled>{{marks[key]}}
<!-- Here it is not updating value from above model-->
<input type="number" class="form-control" ng-model="marks[key]">
</div>
</div>

Rendering Angularjs Template from within controller

Suppose I have following angularjs template
<script type="text/ng-template" id="tmp">
<li>
{{firstname}} {{lastname}}</li>
</script>
and I have two textboxes and a save button like
<input name="firstname" type="text"/>
<input name="lastname" type="text"/>
<button name="save" text="save"/>
when user enters values in firstname and lastname textboxes and press on save button I want these two values to be passed to the template and resultant html should be appended to an existing ul. How can I do it with angular?
You could create a directive to dynamically compile your template and append it to the ul when someone hits the save button, but that's basically the whole purpose of ng-repeat.
Here's how it can work with an ng-repeat instead:
angular.module('main', []);
angular.module('main').controller('MainCtrl', function ($scope) {
$scope.names = [];
$scope.save = function () {
$scope.names.push({first: $scope.firstname, last: $scope.lastname});
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="main" ng-controller='MainCtrl'>
<input name="firstname" type="text" ng-model='firstname'/>
<input name="lastname" type="text"ng-model='lastname'/>
<button name="save" text="save" ng-click='save()'>save</button>
<ul>
<li ng-repeat='name in names'>{{name.first}} {{name.last}}</li>
</ul>
</div>

Input text not being cleared out

I'm trying to clear an input text after saving some data but it just doesn't work. This is what I've tried so far (what it's in comments too):
Thanks in advance for any help!
HTML:
<div id="add-tag">
<h3>Add new tag</h3>
<form name="addTagForm">
<input class="form-control" type="text" ng-model="newTag" ng-change="onChangeTag()">
<button class="btn btn-primary" ng-click="addTag(newTag)">Add Tag</button>
</form>
</div>
JS:
//$scope.master = {};
// Reset scope
$scope.reset = function() {
$scope.newTag = "";
//$scope.newTag = angular.copy($scope.master);
};
$scope.addTag = function(tag) {
// Save some data (this works fine)
// ....
// Reset input field
$scope.reset();
};
UPDATE:
My ng-controller was set to the parent template (I'm using ui.router). Just added it to the child template and it indeed worked.
<div id="add-tag" ng-controller="FormController">
<h3>Add new tag</h3>
<form name="addTagForm">
<input class="form-control" type="text" ng-model="newTag" ng-change="onChangeTag()">
<button class="btn btn-primary" ng-click="addTag(newTag)">Add Tag</button>
</form>
</div>
I am new in angularjs but after trying some thing i got some sort of solution for you. You can check this bin. I have just added a controller :-
function test_c($scope){
$scope.reset = function() {
$scope.newTag = "";
//$scope.newTag = angular.copy($scope.master);
};
$scope.addTag = function(tag) {
// Save some data (this works fine)
// ....
// Reset input field
$scope.reset();
};}
Look at the html part:-
<body ng-app>
<div id="add-tag" ng-controller="test_c">
<h3>Add new tag</h3>
<form name="addTagForm">
<input class="form-control" type="text" ng-model="newTag" ng-change="onChangeTag()">
<button class="btn btn-primary" ng-click="addTag(newTag)">Add Tag</button>
</form>
</div>

Angular- Creating a directive from existing html content/

Assume
You have html that you can not modify the inner contents of- but you CAN modify the element attributes.
Your goal is to perform 3d transformations on the element that are bidirectionally linked to the value of 3 range inputs.
One input for X rotation, Y Rotation and Z Rotation.
In order to do that, I think I need to use a directive-- but if I use a directive it will erase the existing html...
see this codepen for the current version.
HTML
<html ng-app="truck">
<head></head>
<body>
<section ng-controller="TruckCtl">
<section class="controls">
<fieldset>
<legend>Rotation</legend>
<div>
<label for="xRotation">X:</label>
<input id="xRotation" ng-model="Rotation.x" type="range" min="0" max="360">
<span ng-bind="Rotation.x"></span>
</div>
<div>
<label for="yRotation">Y:</label>
<input name="yRotation" ng-model="Rotation.y" type="range" min="0" max="360">
<span ng-bind="Rotation.y"></span>
</div>
<div>
<label for="zRotation">Z:</label>
<input name="zRotation" ng-model="Rotation.z" type="range" min="0" max="360">
<span ng-bind="Rotation.z"></span>
</div>
</fieldset>
</section>
<section class="wrapper">
<div id="truck" ng-model="Rotation">
</div>
</section>
</section>
</body>
</html>
JS
(function(){
"use strict";
var app = angular.module('truck', []);
app.controller("TruckCtl", function($scope){
$scope.Rotation = {
x: 0,
y: 0,
z: 0
};
});
//no dice v
app.filter("rotate", function() {
return function(input) {
return model.style({
"-webkit-transform" : "rotateX(" + Rotation.x + "deg)"
});
console.log(model);
}
});
//Directives are where I ge lost.
app.directive("Rotation", function(){
return function(scope, element, attrs){
//what do?
}
});
})();
also:
I have no idea why this fiddle doesn't work.
I would recommend to get it working by keeping things simple first. Once you have code that works, you can refactor it out into a filter and directive. The angular docs cover how to implement a directive pretty well, you can basically just copy, paste, and modify. If you have specific questions I'm sure you'll find answers here or elsewhere. As far as simple code to achieve your goal; your controller along with this HTML will rotate as specified:
<div id="truck" style="-webkit-transform: rotateX({{Rotation.x}}deg) rotateY({{Rotation.y}}deg) rotateZ({{Rotation.z}}deg);"></div>
Also, BTW - js convention is to use camelCasing. $scope.Rotation should be $scope.rotation (lowercase r). Use PascalCase for constructors. Although it is purely a preference, you'll find most libraries adhere to this convention.
So the TLDR version is that my nesting was off so my scopes were wrong.
Also I should've been using a factory rather than a filter or a directive.
Working example can be found: here
--one caveat is that it doesn't work until you adjust all the values first.
so just move all of the range sliders to 0 and then change them as you please
html
<section ng-app="truck">
<section id="wrapper" ng-controller="Truck">
<section class="controls">
<fieldset>
<legend>Rotation</legend>
<div>
<label for="xRotation">X:</label>
<input id="xRotation" ng-model="Rotation.x" type="range" min="-100" max="100">
[[Rotation.x]]
</div>
<div>
<label for="yRotation">Y:</label>
<input id="yRotation" ng-model="Rotation.y" type="range" min="-100" max="100">
[[Rotation.y]]
</div>
<div>
<label for="zRotation">Z:</label>
<input id="zRotation" ng-model="Rotation.z" type="range" min="-100" max="100">
[[Rotation.z]]
</div>
</fieldset>
<fieldset>
<legend>Translation</legend>
<div>
<label for="xTranslation">X:</label>
<input id="xTranslation" ng-model="Translation.x" type="range" min="-100" max="100">
[[Translation.x]]
</div>
<div>
<label for="yTranslation">Y:</label>
<input id="yTranslation" ng-model="Translation.y" type="range" min="-100" max="100">
[[Translation.y]]
</div>
<div>
<label for="zTranslation">Z:</label>
<input id="zTranslation" ng-model="Translation.z" type="range" min="-100" max="100">
[[Translation.z]]
</div>
</fieldset>
</section>
<div id="zderp">
<div id="truck" style="-webkit-transform: rotateX([[Rotation.x]]deg) rotateY([[Rotation.y]]deg) rotateZ([[Rotation.z]]deg) translateX([[Translation.x]]px) translateY([[Translation.y]]px) translateZ([[Translation.z]]px)">
</div>
</div>
</section>
</section>
js
var app = angular.module('truck', []).config(function($interpolateProvider){
"use strict";
$interpolateProvider.startSymbol('[[').endSymbol(']]');
});
app.factory('Rotation', function(){
return {
x : '1',
y : '1',
z : '1'
}
});
function TruckCtl($scope, Rotation){
$scope.x = Rotation.x;
$scope.x = Rotation.y;
$scope.x = Rotation.z;
}
function Truck($scope, Rotation){
$scope.x = Rotation.x;
$scope.x = Rotation.y;
$scope.x = Rotation.z;
}

Resources