Hiding and Showing Edit Input not working(Angular) - html

I'm trying to make an Edit button, with an input field that appears/disappears when the button is pressed. It was working previously, however when I tried to make a Display form, it doesn't seem to recognize the "title.value" This is very strange. I'm using Boolean for an "edit" variable combined with a *ngIf to show/hide the form. If I take the *ngIf="edit" off, it works normally as a form that displays what you're written. Am I missing something?
Here's the HTML:
<input type="text" #title *ngIf="edit"/>
<button (click)="edit = !edit">Edit</button>
<button (click)="getTitle(title.value)">Get Title</button>
<h2>{{groupTitle}}</h2>
and here's the .ts:
public edit = false;
public groupTitle = "";
getTitle(val) {
this.groupTitle = val;
}

You have a problem with implementing together the ngIf directive and a reference to your input element as #title. In that case you can use hidden instead of ngIf.
Here's your html:
<input type="text" #title [hidden]="!edit"/>
<button (click)="edit = !edit">Edit</button>
<button (click)="getTitle(title.value)">Get Title</button>
<h2>{{groupTitle}}</h2>
There are couple more elegant ways to bind a value and render it on a page.
The first one is to get rid of the Get title button and use (input) method directly on an input element.
In that case, Html looks like:
<input type="text" #title *ngIf="edit" (input)="getTitle(title.value)"/>
<button (click)="edit = !edit">Edit</button>
<h2>{{groupTitle}}</h2>
The second one is to use [(ngModel]) instead of the getTitle method and bind your input value directly to the groupTitle variable.
Html will look like:
<input type="text" #title *ngIf="edit" [(ngModel)]="groupTitle"/>
<button (click)="edit = !edit">Edit</button>
<h2>{{groupTitle}}</h2>
Your .ts file:
edit = false;
groupTitle = "";

Related

How to reset check status in html

I have popup in HTML
<div id="term_flags" class="term_flags">
<div class="modal-users-content flagsContent">
<div class="modal-users-header">
<span class="close" ng-click="closeFlagsPopup()">×</span>
<a> Check terminal flags </a>
</div>
<div class="modal-flags-body">
<div class="checkBoxes">
<div class="checkerDiv">
<input type="checkbox" ng-model='reservedFlag' ng-click='changeReservedStatus(reservedFlag)' value="flag" ng-checked="reservedFlag"> Reserved
</div>
<div class="checkerDiv">
<input type="checkbox" ng-model='seasonFlag' ng-click='changeSeasonStatus(seasonFlag)' value="flag" ng-checked="seasonFlag"> Season
</div>
<div class="checkerDiv">
<input type="checkbox" ng-model='networkFlag' ng-click='changeNetworkStatus(networkFlag)' value="flag" ng-checked="networkFlag"> Network
</div>
</div>
<div class="saveFlags">
<button class="button button6" name="changeFlags" value="Change Flags" type="submit" ng-click="saveFlags(item.terminalId)"> Save <p> </button>
</div>
</div>
<div class="modal-footer"></div>
</div>
</div>
this div's display is none in the beginning. but some ng-click is called from outside of this div and display is changed from none to block and initializes checkbox statuses in this angular function
$scope.changeFlagStatus = function(item)
{
$scope.reservedFlag=(item.reservedFlag=='T')?true:false;
$scope.networkFlag=(item.networkFlag=='T')?true:false;
$scope.seasonFlag=(item.seasonFlag=='T')?true:false;
document.getElementById('term_flags').style.display = "block";
}
everything is okay , but when i click on reservedFlag changeReservedStatus(reservedFlag) method was called and change reservedFlag's checked status
$scope.changeReservedStatus = function(item) {
$scope.reservedForSave=item;
}
I saved this status in other variable and close my popup windows document.getElementById('term_flags').style.display=none
when i open this popup window again my function changeFlagStatus(item) is called again and initializes my variables for checkbox correctly but my checkbox are incorrect checked .
In example when i opened my popup window first time my variables after initialize were
$scope.reservedFlag=true;
$scope.networkFlag=false;
$scope.seasonFlag=true;
and my checkbox statuses were
reservedFlag = checked
networkFlag = unchecked
seasonFlag = checked
then i clicked on reservedFlag and changed his status from checked to unchecked and close my popup windows.
then i opened it second time and changeFlagStatus(item) method is called again to initialize my variables again for checkbox statuses
and i want to get
reservedFlag = checked
networkFlag = unchecked
seasonFlag = checked
again, but result is
reservedFlag = unchecked
networkFlag = unchecked
seasonFlag = checked
How can i get it ?
Angularjs won't work pretty good with $scope's properties for primitive variables when used again and again.
I would recommend you to declare an object to scope and set these flags as properties to this object.
$scope.flags = {};
$scope.changeFlagStatus = function(item)
{
$scope.flags.reservedFlag=(item.reservedFlag=='T')?true:false;
$scope.flags.networkFlag=(item.networkFlag=='T')?true:false;
$scope.flags.seasonFlag=(item.seasonFlag=='T')?true:false;
document.getElementById('term_flags').style.display = "block";
}
and the html part as
<input type="checkbox" ng-model='flags.reservedFlag' ng-change='changeReservedStatus()' value="flag" ng-checked="flags.reservedFlag"> Reserved
Instead of ng-click, I would recommend to use ng-change because that is the event to be used with checkbox. If you use ng-change, the injection of the model as a parameter can be avoided which helps in utilizing angularjs's feature of 2-way binding.
You can add ng-true-value and ng-false-value to the checkbox with true and false to make it more easier to handle instead of ng-value.
I would write the html part like this.
<input type="checkbox" ng-model='flags.reservedFlag' ng-change='changeReservedStatus()' ng-true-value="true" ng-false-value="false"> Reserved
Hope this will fix the issue.

Angular 2 html form validation

I've created a form using html validations with Angular 2.
I want to to check the sate of the inputs (no empty, correct format, etc) when the user click to a certain button. At the moment I'm doing it as following:
<form id="memberForm" #memberForm="ngForm" >
<input
type="text"
id="MemberName"
required
name="MemberName"
[(ngModel)]="newMember.name">
</form>
<div
[ngClass]="{'button_disabledButton' : !memberForm?.valid}"
(click)="onSubmit(memberForm?.valid, memberForm);">
<span>Next</span>
</div>
With this, I'm only evaluating the input once clicked and focus out. How can I make it hapens when the user click in the "Next" element?
You should make getter/setter solution for your ngModel input.
In the .ts file in the appropriate class put this:
savedVar:string = '';
get variable(): string {
return this.savedVar;
}
set variable(str: string) {
this.savedVar = str;
// do your validation
}
In template use ngModel=variable like this:
<input [(ngModel)]="variable">

Changing CSS property if no input is provided (Angular JS)

I am making a quiz using angular js.The first page of the quiz requires you to enter your name and doesn't allow you to go further if no input is provided.I want to animate input field more like the shake animation on this site (http://daneden.github.io/animate.css/) if the input field is empty and the user presses the start button.Please help me out.
CODE html :
<p>What's your name?</p>
<input type = "text" class = "playername" ng-model = "playername">
<h2>Welcome {{playername}}!</h2>
<p>Click start if you're ready!</p>
<p class = "btn" ng-click = "startQuiz()">START</p>
CODE angular :
$scope.presentQues = -1;
$scope.startQuiz = function(){
if ($scope.playername != null){
$scope.presentQues = 0;
}
}
PS. this is not the full code.
Building on #Chris's answer, if you wrap it in a form, you can also use the form.$submitted variable to check if the form has been submitted.
ng-class uses the following format: ng-class={'css-class':truthy-condition-to-evaluate
Try the following code (this will have to be changed if you already are wrapping everything in a form):
<div ng-controller="myCtrl as ctrl">
<form name="myForm">
<p>What's your name?</p>
<input type = "text" name="playername" class = "playername" ng-class="{'animated shake': !ctrl.playername && myForm.$submitted}" ng-model = "ctrl.playername">
<h2>Welcome {{ctrl.playername}}!</h2>
<p>Click start if you're ready!</p>
<input type="submit" class = "btn" ng-click = "startQuiz()" value="START">
</form>
</div>
Now, if the player submits the form without typing anything, angular will apply the animated and shake css classes to the text input.
Look at my plunker to view it in action.
There are many ways of doing this, one I can see is using ng-class.
<!-- add class 'bounceInUp' if the scope var 'isEmpty' is true -->
<input type="text" class="playername" ng-class={'bounceInUp':isEmpty,} ng-model="playername">

How do I reset a form including removing all validation errors?

I have an Angular form. The fields are validated using the ng-pattern attribute. I also have a reset button. I'm using the Ui.Utils Event Binder to handle the reset event like so:
<form name="searchForm" id="searchForm" ui-event="{reset: 'reset(searchForm)'}" ng-submit="search()">
<div>
<label>
Area Code
<input type="tel" name="areaCode" ng-model="areaCode" ng-pattern="/^([0-9]{3})?$/">
</label>
<div ng-messages="searchForm.areaCode.$error">
<div class="error" ng-message="pattern">The area code must be three digits</div>
</div>
</div>
<div>
<label>
Phone Number
<input type="tel" name="phoneNumber" ng-model="phoneNumber" ng-pattern="/^([0-9]{7})?$/">
</label>
<div ng-messages="searchForm.phoneNumber.$error">
<div class="error" ng-message="pattern">The phone number must be seven digits</div>
</div>
</div>
<br>
<div>
<button type="reset">Reset</button>
<button type="submit" ng-disabled="searchForm.$invalid">Search</button>
</div>
</form>
As you can see, when the form is reset it calls the reset method on the $scope. Here's what the entire controller looks like:
angular.module('app').controller('mainController', function($scope) {
$scope.resetCount = 0;
$scope.reset = function(form) {
form.$setPristine();
form.$setUntouched();
$scope.resetCount++;
};
$scope.search = function() {
alert('Searching');
};
});
I'm calling form.$setPristine() and form.$setUntouched, following the advice from another question here on Stack Overflow. The only reason I added the counter was to prove that the code is being called (which it is).
The problem is that even after reseting the form, the validation messages don't go away. You can see the full code on Plunker. Here's a screenshot showing that the errors don't go away:
I started with the comment from #Brett and built upon it. I actually have multiple forms and each form has many fields (more than just the two shown). So I wanted a general solution.
I noticed that the Angular form object has a property for each control (input, select, textarea, etc) as well as some other Angular properties. Each of the Angular properties, though, begins with a dollar sign ($). So I ended up doing this (including the comment for the benefit of other programmers):
$scope.reset = function(form) {
// Each control (input, select, textarea, etc) gets added as a property of the form.
// The form has other built-in properties as well. However it's easy to filter those out,
// because the Angular team has chosen to prefix each one with a dollar sign.
// So, we just avoid those properties that begin with a dollar sign.
let controlNames = Object.keys(form).filter(key => key.indexOf('$') !== 0);
// Set each control back to undefined. This is the only way to clear validation messages.
// Calling `form.$setPristine()` won't do it (even though you wish it would).
for (let name of controlNames) {
let control = form[name];
control.$setViewValue(undefined);
}
form.$setPristine();
form.$setUntouched();
};
$scope.search = {areaCode: xxxx, phoneNumber: yyyy}
Structure all models in your form in one place like above, so you can clear it like this:
$scope.search = angular.copy({});
After that you can just call this for reset the validation:
$scope.search_form.$setPristine();
$scope.search_form.$setUntouched();
$scope.search_form.$rollbackViewValue();
There doesn't seem to be an easy way to reset the $errors in angular. The best way would probably be to reload the current page to start with a new form. Alternatively you have to remove all $error manually with this script:
form.$setPristine(true);
form.$setUntouched(true);
// iterate over all from properties
angular.forEach(form, function(ctrl, name) {
// ignore angular fields and functions
if (name.indexOf('$') != 0) {
// iterate over all $errors for each field
angular.forEach(ctrl.$error, function(value, name) {
// reset validity
ctrl.$setValidity(name, null);
});
}
});
$scope.resetCount++;
You can add a validation flag and show or hide errors according to its value with ng-if or ng-show in your HTML. The form has a $valid flag you can send to your controller.
ng-if will remove or recreate the element to the DOM, while ng-show will add it but won't show it (depending on the flag value).
EDIT: As pointed by Michael, if form is disabled, the way I pointed won't work because the form is never submitted. Updated the code accordingly.
HTML
<form name="searchForm" id="searchForm" ui-event="{reset: 'reset(searchForm)'}" ng-submit="search()">
<div>
<label>
Area Code
<input type="tel" name="areaCode" ng-model="areaCode" ng-pattern="/^([0-9]{3})?$/">
</label>
<div ng-messages="searchForm.areaCode.$error">
<div class="error" ng-message="pattern" ng-if="searchForm.areaCode.$dirty">The area code must be three digits</div>
</div>
</div>
<div>
<label>
Phone Number
<input type="tel" name="phoneNumber" ng-model="phoneNumber" ng-pattern="/^([0-9]{7})?$/">
</label>
<div ng-messages="searchForm.phoneNumber.$error">
<div class="error" ng-message="pattern" ng-if="searchForm.phoneNumber.$dirty">The phone number must be seven digits</div>
</div>
</div>
<br>
<div>
<button type="reset">Reset</button>
<button type="submit" ng-disabled="searchForm.$invalid">Search</button>
</div>
</form>
JS
$scope.search = function() {
alert('Searching');
};
$scope.reset = function(form) {
form.$setPristine();
form.$setUntouched();
$scope.resetCount++;
};
Codepen with working solution: http://codepen.io/anon/pen/zGPZoB
It looks like I got to do the right behavior at reset. Unfortunately, using the standard reset failed. I also do not include the library ui-event. So my code is a little different from yours, but it does what you need.
<form name="searchForm" id="searchForm" ng-submit="search()">
pristine = {{searchForm.$pristine}} valid ={{searchForm.$valid}}
<div>
<label>
Area Code
<input type="tel" required name="areaCode" ng-model="obj.areaCode" ng-pattern="/^([0-9]{3})?$/" ng-model-options="{ allowInvalid: true }">
</label>
<div ng-messages="searchForm.areaCode.$error">
<div class="error" ng-message="pattern">The area code must be three digits</div>
<div class="error" ng-message="required">The area code is required</div>
</div>
</div>
<div>
<label>
Phone Number
<input type="tel" required name="phoneNumber" ng-model="obj.phoneNumber" ng-pattern="/^([0-9]{7})?$/" ng-model-options="{ allowInvalid: true }">
</label>
<div ng-messages="searchForm.phoneNumber.$error">
<div class="error" ng-message="pattern">The phone number must be seven digits</div>
<div class="error" ng-message="required">The phone number is required</div>
</div>
</div>
<br>
<div>
<button ng-click="reset(searchForm)" type="reset">Reset</button>
<button type="submit" ng-disabled="searchForm.$invalid">Search</button>
</div>
</form>
And JS:
$scope.resetCount = 0;
$scope.obj = {};
$scope.reset = function(form_) {
$scope.resetCount++;
$scope.obj = {};
form_.$setPristine();
form_.$setUntouched();
console.log($scope.resetCount);
};
$scope.search = function() {
alert('Searching');
};
Live example on jsfiddle.
Note the directive ng-model-options="{allowinvalid: true}". Use it necessarily, or until the entry field will not be valid, the model value is not recorded. Therefore, the reset will not operate.
P.S. Put value (areaCode, phoneNumber) on the object simplifies purification.
Following worked for me
let form = this.$scope.myForm;
let controlNames = Object.keys(form).filter(key => key.indexOf('$') !== 0);
for (let name of controlNames) {
let control = form [name];
control.$error = {};
}
In Short: to get rid of ng-messages errors you need to clear out the $error object for each form item.
further to #battmanz 's answer, but without using any ES6 syntax to support older browsers.
$scope.resetForm = function (form) {
try {
var controlNames = Object.keys(form).filter(function (key) { return key.indexOf('$') !== 0 });
console.log(controlNames);
for (var x = 0; x < controlNames.length; x++) {
form[controlNames[x]].$setViewValue(undefined);
}
form.$setPristine();
form.$setUntouched();
} catch (e) {
console.log('Error in Reset');
console.log(e);
}
};
I had the same problem and tried to do battmanz solution (accepted answer).
I'm pretty sure his answer is really good, but however for me it wasn't working.
I am using ng-model to bind data, and angular material library for the inputs and ng-message directives for error message , so maybe what I will say will be useful only for people using the same configuration.
I took a lot of look at the formController object in javascript, in fact there is a lot of $ angular function as battmanz noted, and there is in addition, your fields names, which are object with some functions in its fields.
So what is clearing your form ?
Usually I see a form as a json object, and all the fields are binded to a key of this json object.
//lets call here this json vm.form
vm.form = {};
//you should have something as ng-model = "vm.form.name" in your view
So at first to clear the form I just did callback of submiting form :
vm.form = {};
And as explained in this question, ng-messages won't disappear with that, that's really bad.
When I used battmanz solution as he wrote it, the messages didn't appear anymore, but the fields were not empty anymore after submiting, even if I wrote
vm.form = {};
And I found out it was normal, because using his solution actually remove the model binding from the form, because it sets all the fields to undefined.
So the text was still in the view because somehow there wan't any binding anymore and it decided to stay in the HTML.
So what did I do ?
Actually I just clear the field (setting the binding to {}), and used just
form.$setPristine();
form.$setUntouched();
Actually it seems logical, since the binding is still here, the values in the form are now empty, and angular ng-messages directive is triggering only if the form is not untouched, so I think it's normal after all.
Final (very simple) code is that :
function reset(form) {
form.$setPristine();
form.$setUntouched();
};
A big problem I encountered with that :
Only once, the callback seems to have fucked up somewhere, and somehow the fields weren't empty (it was like I didn't click on the submit button).
When I clicked again, the date sent was empty. That even more weird because my submit button is supposed to be disabled when a required field is not filled with the good pattern, and empty is certainly not a good one.
I don't know if my way of doing is the best or even correct, if you have any critic/suggestion or any though about the problem I encountered, please let me know, I always love to step up in angularJS.
Hope this will help someone and sorry for the bad english.
You can pass your loginForm object into the function ng-click="userCtrl.login(loginForm)
and in the function call
this.login = function (loginForm){
loginForm.$setPristine();
loginForm.$setUntouched();
}
So none of the answers were completely working for me. Esp, clearing the view value, so I combined all the answers clearing view value, clearing errors and clearing the selection with j query(provided the fields are input and name same as model name)
var modelNames = Object.keys($scope.form).filter(key => key.indexOf('$') !== 0);
modelNames.forEach(function(name){
var model = $scope.form[name];
model.$setViewValue(undefined);
jq('input[name='+name+']').val('');
angular.forEach(model.$error, function(value, name) {
// reset validity
model.$setValidity(name, null);
});
});
$scope.form.$setPristine();
$scope.form.$setUntouched();

Refresh Angular output on input reset

I have several <input> fields within a <form>. Angular takes the value from those fields regardless of the <form> (which is actually there only for Bootstrap to apply the right styles to inner fields).
Now, I want to be able to reset the fields, and so get Angular update the output associated to them as well. However, a regular <input type="reset"/> button is not working. It resets the values of all the <input> fields, but Angular is not refreshing the output that is based on the fields after it.
Is there any way to tell Angular to refresh the outputs based on the current state of the fields? Something like a ng-click="refresh()"?
Let's say you have your model called address. You have this HTML form.
<input [...] ng-model="address.name" />
<input [...] ng-model="address.street" />
<input [...] ng-model="address.postalCode" />
<input [...] ng-model="address.town" />
<input [...] ng-model="address.country" />
And you have this in your angular controller.
$scope.reset = function() {
$scope.defaultAddress = {};
$scope.resetAddress = function() {
$scope.address = angular.copy($scope.defaultAddress);
}
};
JSFiddle available here.
You should have your values tied to a model.
<input ng-model="myvalue">
Output: {{myvalue}}
$scope.refresh = function(){
delete $scope.myvalue;
}
JSFiddle: http://jsfiddle.net/V2LAv/
Also check out an example usage of $pristine here:
http://plnkr.co/edit/815Bml?p=preview