View form surroundet with ng-if is clearing model - javascript

I'm trying to send some data from a form to my controller. Surrounded in the template file with an if. So my working example (without ng-if) is:
View
<form ng-submit="activate()">
<div class="md-form-group">
<input type="password" name="password" ng-model="input.password" required>
<label>Password</label>
</div>
<button type="submit" class="btn primary btn-block p-x-md">Submit</button>
</form>
Controller
$scope.showDescription1 = false;
$scope.activate = function() {
console.log($scope.input);
return;
...
}
Result
It is what I expect... The model object with password field. So now the problem: When I wrapped all the view with an ng-if, the console.log will write undefined.
Modified view
<div ng-if="!showDescription1" class="m-b text-sm">
<span>
This is the second description...
</span>
<form ng-submit="activate()">
<div class="md-form-group">
<input type="password" name="password" ng-model="input.password" required>
<label>Password</label>
</div>
<button type="submit" class="btn primary btn-block p-x-md">Submit</button>
</form>
</div>
Controller
(no change)
Result
The console.log call will write the undefined value. I don't know why, but the ng-if statement is clearing my model? However why?

ng-if will attach the element to DOM when the expression ng-if="!showDescription1" is evaluated as true and removes the element when it evaluates to `false'. For this reason any of your user input will be lost.
For your case, you need to use ng-show or ng-hide which will not re-render the element and instead change their display. So the user input persists.

ng-if creates its own child scope whenever it evaluates to true. So the value of "input" you are logging in console.log is inside the new child scope created by the ng-if and not the controller scope.
Below description from angular documentation here explains it :
Note that when an element is removed using ngIf its scope is destroyed
and a new scope is created when the element is restored. The scope
created within ngIf inherits from its parent scope using prototypal
inheritance. An important implication of this is if ngModel is used
within ngIf to bind to a javascript primitive defined in the parent
scope. In this case any modifications made to the variable within the
child scope will override (hide) the value in the parent scope.
Now, to get your code working , use $parent to the model as shown below :
<div ng-if="!showDescription1" class="m-b text-sm">
<span>
This is the second description...
</span>
<form ng-submit="activate()">
<div class="md-form-group">
<input type="password" name="password" ng-model="$parent.input.password" required>
<label>Password</label>
</div>
<button type="submit" class="btn primary btn-block p-x-md">Submit</button>
</form>

Try this it is working as per your expectation :
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl',function($scope) {
$scope.showDescription1 = false;
$scope.activate = function() {
console.log($scope.input);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="MyCtrl">
<div ng-if="!showDescription1" class="m-b text-sm">
<span>
This is the second description...
</span>
<form ng-submit="activate()">
<div class="md-form-group">
<label>Password</label>
<input type="password" name="password" ng-model="input.password" required>
</div>
<button type="submit" class="btn primary btn-block p-x-md">Submit</button>
</form>
</div>
</div>

Related

How do I make ngFor with input inside not repeat the typing value?

I need to make multiple inputs with ngFor but when I enter a word, it is repeated in all the inputs there are, how can I solve this?
my code:
<div class="" *ngFor="let publication of publications">
...
<form #newCommentForm="ngForm" (ngSubmit)="onSubmit(newCommentForm, $event, publication._id)">
<div class="make-comment" >
<img src="{{url+ 'get-image-user/' + publication.user.image }}" *ngIf="publication.user.image" class="rounded-circle-mini align-self-center">
<input type="text" name="#text" #text="ngModel" [(ngModel)]="comment.text" id="input-coment" class="form-control" required placeholder="Your comment">
<button class="btn btn-sm btn-secondary" style="color: #fff;" type="submit"><i class="bi bi-arrow-bar-left"></i></button>
</div>
</form>
</div>
You're binding the variable 'comment.text' to every input [model]. Meaning, its value is shared between all your input scopes. You need to use 'publication', which is only scoped to each input.
*ngFor="let publication of publications"
Change [(ngModel)]="comment.text" to something like [(ngModel)]="publication.text"
You are binding all inputs to a single property comment.text. You should create one property for each input and bind input with it.

How do I get the value of a text field using AngularJS?

I want to get the value of a text field value using AngularJS when a form is submitted.
The code below always shows "undefined".
html:
<form ng-submit="AdvanceSearchSubmit($event)" name="AdvanceSearch" novalidate>
<p ng-show="!AdvanceSearch.SearchKeyWord.$pristine && AdvanceSearch.SearchKeyWord.$invalid" class="text-danger">Text Cannot Be Empty!</p>
<div ng-hide="AdvanceSearchModel" class="input-group">
<input name="SearchKeyWord" ng-model="SearchKeyWord" id="SearchKeyWord" class="form-control" placeholder="Search in timeline...." type="text" required>
<span class="input-group-btn" ng-click="isAdvanceSearch='false'; SearchPost(0,'true')">
<button ng-disabled="AdvanceSearch.$invalid" type="submit" name="search" id="search-btn" class="btn btn-flat">
<i class="fa fa-search"></i>
</button>
</span>
</div>
</form>
one attempt:
$scope.AdvanceSearchSubmit = function(event)
{
alert(event.target.value);
};
another attempt:
$scope.AdvanceSearchSubmit = function(event)
{
alert(event.SearchKeyWord.value);
};
instead of event pass the SearchKeyWord as a parameter
ng-submit="AdvanceSearchSubmit(SearchKeyWord)"
controller
$scope.AdvanceSearchSubmit = function(keyWord)
{
alert(keyWord);
};
You don't need to pass the event at all to your AdvanceSearchSubmit on submit. You already have your values available inside $scope like ng-model for input field like ng-model="SearchKeyWord"
alert($scope.SearchKeyWord); //access value from `$scope` directly

AngularJS: Setting value of form field to various object properties

I have a simple AngularJS dynamic form that is bound by ng-model to a property modelParams.value. Each form field displays the value of modelParams.value However, I would like to have a button called "Default" that sets the values of all of the form fields to some other property in this associative array such as modelParams.defaultValue, or modelParams.oldValue. I assume that once the "Default" button is pressed this would override the value of ng-model="modelParams.value".
Here is the form:
<form name="modelParamsForm">
<div class="form-group" ng-repeat="modelParam in modelParams">
<div class="row">
//INPUT FORM FIELDS
<input type="number" class="form-control input-sm" required ng-
model="modelParam.value" >
</div>
</div>
<button class="btn btn-primary btn-sm" ng-
click="updateModelParams(modelParams, modelParamsForm)">
</button>
//DEFAULT BUTTON
<button type="button" class="btn btn-default btn-sm" ng-
click="default()">Default</button>
</form>
My JSON looks like this:
[{"model":"MAF","paramname":"CascDefaultSpreadOverride","minvalue":"0","maxvalue":"100","description":"The defaault repo spread override to use for CASC positions.","defaultvalue":1.0,"value":1.0,"datatype":"FLOAT"},{"model":"MAF","paramname":"DefaultLotSize","minvalue":"1","maxvalue":"1000","description":"The minimum lot size that must be met for a collateral allocation.","defaultvalue":1.0,"value":1.0,"datatype":"INTEGER"},{"model":"MAF","paramname":"HtbColdHaircut","minvalue":"0","maxvalue":"100","description":"The haircut to apply to positions with a Cold HTB category.","defaultvalue":0.1,"value":0.1,"datatype":"FLOAT"},{"model":"MAF","paramname":"HtbExtraHotHaircut","minvalue":"0","maxvalue":"100","description":"The haircut to apply to positions with a Extra-Hot HTB category.","defaultvalue":0.9,"value":0.9,"datatype":"FLOAT"},]
$scope.field = 'value';
$scope.change = function() {
$scope.field = 'oldValue';
}
...ng repeat blabla
<input ng-model="modelParam[field]"/>
...
<button ng-click="change()">Change</button>
EDIT: Here is a working demo: http://jsfiddle.net/zy94an54/

AngularJs: Form inside ng-if not accessible from controller

I have a form inside ng-if directive. I want to check the form validation in controller using $valid.
<div ng-if="paymentMethod == 12">
<form name="creditForm" id="cc-form" novalidate>
<div class="form-group">
<label for="cardNumber">Card Number</label>
<input type="text" autofocus class="form-control" name="card_number" ng-minlength="16" id="cardNumber" ng-model="creditCardNumber" required>
<div class="red-text" ng-messages="creditForm.card_number.$error" ng-if="creditForm.card_number.$dirty || creditForm.$submitted">
<div ng-message="required">##global.Card_Num_Required##</div>
<div ng-message="maxlength">##global.Card_Num_MinLength##</div>
<div ng-message="minlength">##global.Card_Num_MaxLength##</div>
<div ng-message="minlength">##global.Card_Num_Numeric ##</div>
</div>
</div>
and trying to check valid form in controller
if ($scope.$parent.creditForm.$valid) {
alert('valid');
} else {
alert('not valid');
}
but the form is not accessible from controller.
The ngIf directive removes or recreates a portion of the DOM tree based on an {expression}. If the expression assigned to ngIf evaluates to a false value then the element is removed from the DOM, otherwise a clone of the element is reinserted into the DOM.
you can go throgh this link doc and also my answer here answer
You can use ng-show instead of ng-if if its feasible to you.
It works fine when you use auxiliary object in your controller.
In Your Controller file
$scope.page = {
creditForm:null
};
in your HTML file
<div ng-if="paymentMethod == 12">
<ng-form name="page.creditForm" id="cc-form" novalidate>
<div class="form-group">
<label for="cardNumber">Card Number</label>
<input type="text" autofocus class="form-control" name="card_number" ng-minlength="16" id="cardNumber" ng-model="creditCardNumber" required>
<div class="red-text" ng-messages="page.creditForm.card_number.$error" ng-if="page.creditForm.card_number.$dirty || page.creditForm.$submitted">
<div ng-message="required">##global.Card_Num_Required##</div>
<div ng-message="maxlength">##global.Card_Num_MinLength##</div>
<div ng-message="minlength">##global.Card_Num_MaxLength##</div>
<div ng-message="minlength">##global.Card_Num_Numeric ##</div>
</div>
</div>
</ng-form>
in this model you can saftly use ng-form inside ng-if
This happens because ngIf creates a new scope, so name="form" will register the form controller on that new scope (which is a child of the ctrl scope). You can solve this, by binding to an existing object on the target scope. (Alternatively, you can bind to the controller and use the controllerAs syntax, which is generally considered a good practice.)
This is because of how prototypal inheritance works in JavaScript.
You can find a sample plunker here
<form name="data.form" novalidate ng-if=true>
http://plnkr.co/edit/2Ip3gNPdUWWV0zK8PNJr?p=preview
$scope.$watch('creditForm.$valid', function(newVal) {
//$scope.valid = newVal;
alert('valid');
});

How to use ngModelOptions and $rollbackViewValue() in AngularJS 1.3

I have a problem with my input fields in my modal view.
When I take a change in the input fields then it is updating the table list but when I leave the page and go back to this page with the table list then die changes are disappeared.
This is my modal view:
<form class="form-horizontal" name="editForm" novalidate>
<div class="modal-body">
<div class="form-group-sm has-feedback">
<label class="control-label">Firstname</label>
<input type="text"
class="form-control"
name="Fname"
ng-model="selected.fname"
ng-model-options="{updateOn: 'updateItem'}"
ng-required="true"
/>
</div>
</div>
//the same input field for lastname
...
<div class="modal-footer">
<button class="btn btn-default" ng-click="createItem(selected)" type="submit">Erstellen</button>
<button class="btn btn-default" ng-click="updateItem(selected)"> Ă„ndern</button>
<button class="btn btn-default" ng-click="cancel()">Abbrechen</button>
</div>
</form>
Modal Ctrl:
$scope.cancel = function () {
$scope.editForm.$rollbackViewValue();
$modalInstance.dismiss('cancel');
}
$scope.updateItem = function (updateItem) {
CrudService.update(updateItem);
$scope.ok();
}
Crud Service:
...
update: function (updateItem) {
updateItem.$update();
},
...
I have only seen examples of $rollbackViewValue() with one input field and the code: $scope.myForm.inputName.$rollbackViewValue() but I have more than one input fields?
you should call $rollbackViewValue() through the form name:
editForm.$rollbackViewValue()
call it in your template:
{{editForm.$rollbackViewValue.toString()}}
and you will see how it actually works:
function () {
forEach(controls, function(control) {
control.$rollbackViewValue();
});
}
A little late but for others reference (I came across this looking for another issue with $rollbackViewValue).
Using $rollbackViewValue in controller: to use $scope to reference the form from the controller, you have to use the ng-form attribute on a child element of the form (like for instance the form-group div in your example).
That makes $scope.editForm.$rollbackViewValue() available in the controller and resets the entire form.
For cases where buttons are inside the form, using ng-submit and ng-model-options="{ updateOn: 'submit' }" on input fields, then adding 'type=button' attribute to cancel button element (so submit isn't triggered) is a quick solution.
Example:
https://embed.plnkr.co/IQ4vvutC3tcHvVBH0821/

Categories

Resources