Angular: how to initialize textarea with default value - html

I built an app that showing messages, when the user press on edit i want the message textarea to be initialized with it's value i create a factory called notification to get the message from my data base and in the controller i called this factory:
$scope.notification = notification.getNotification($stateParams.id);
$scope.notification.then(
function(notification) {
$scope.notification = notification;
console.log($scope.notification.message);
},
function(response) {
console.log('error fetching the notification', response);
}
);
and the HTML :
<textarea ng-model="item.message" class="form-control" ng-init="item.message={{notification.message}}"></textarea>
The textarea kept empty and this what i got in my elements inspector:
<textarea ng-model="item.message" class="form-control ng-pristine ng-untouched ng-valid" ng-init="item.message=hello"></textarea>

ng-init has one special use case with ng-repeat, see the ng-init documents for details on what it is meant to be used for.
You should just set the item.message to some value in your controller that is handling the scope for this section of the view. Basically set:
$scope.item = {message:$scope.notification.message};
or if $scope.item is already an object:
$scope.item.message = $scope.notification.message;

Related

Angular input's ngModel and Value don't work together

I have a problem with the form in angular. My goal is to make a form that is filled with default values ​​that can be changed. After validating the form, it sends the data to the MySQL database.
This is component.html code:
<form #adopt="ngForm" (ngSubmit)="success()">
<label for="email">Email:</label>
<input type="email" name="email" [(ngModel)]="adoptions.email" #email="ngModel">
<label for="animal">Twój wybór to:</label>
<input type="text" name="animal" [(ngModel)]="adoptions.animal" #email="ngModel">
<button [disabled]="adopt.form.invalid" type="submit">Adoptuj</button>
<button (click)="getAnimal('')" class="disable">Odznacz swój wybór</button>
</form>
This is typeScript code:
export class AdoptpageComponent implements OnInit {
adoptions = new Adoptions();
sessionValue
animal
value
msg='';
constructor(private userService: UserService, private shared: SharedService, private _service
: AdoptService, private _router : Router) {
}
ngOnInit(): void {
this.getUsers();
this.sessionValue = sessionStorage.getItem('email');
}
getAnimal(arg) {
this.animal = arg;
}
success() {
this._service.create(this.adoptions).subscribe(
data => {
console.log("dziala");
this._router.navigate(['/adopt'])
},
error => {
console.log("nie dziala");
this.msg = error.error;
}
)
}
}
The code I posted above works, but only when I enter the value into the form from the keyboard. I want the value from sessionValue to be retrieved automatically in the first form and animal in the second. I managed to achieve it when instead of ngModel I entered:
<input type="email" name="email" [value]="sessionValue" #email="ngModel">
But then the form does not work (it does not send data to the database). Unfortunately, when both are used, [value] = "sessionValue" does not work
<input type="email" name="email" [value]="sessionValue" [(ngModel)]="adoptions.email" #email="ngModel">
do you have an idea what to do to be able to submit the form with the default value?
first: you are binding adoptions.email and adoptions.animal to ngModel, but they are empty(or even worse - null or undefined) when ngOnInit is fired, that is why your inputs are empty. They get value once you introduce text in inputs, that is why you are able to successfully execute this._service.create
second: you are causing a value binding conflict. The source of ngModel is different from the source of value. Once ngOnInit is fired value tries to load the value of sessionValue in input and ngModel tries to load nothing, as its source is empty
There is no need to use value if you have ngModel. You just have to set up start point value for its source variable. like below example
ngOnInit(): void {
adoptions.email = somehowGetEmail()
adoptions.animal= somehowGetAnimal()
}
And that's all you have to do, if you insist on using ngModels.
But in general this looks like a lot of unnccessary bindings. Since these are a form inputs you should be using form's preimplemented features for value bindings. Check docs for angular FormBuilder, formControl

How do you add a value to datepicker from an Angular Factory?

i have an Angular Factory that gets a single date from the backend of my spring application, and i wanted to add it to an Input so the calendar input is always set with the date obtained from the backend, without the possibility for the user to change it. How could i achieve this? Should i put it on my controller or directly on the button? This is my code:
Factory(concatenated with other .factory):
.factory('DataInizioGeneraCalendario', function ($resource) {
return $resource('rest/anagrafica/dataInizioGeneraCalendario', {
get: {
method: 'GET'
}
});
Controller Function:
$scope.generaCalendario = function () {
$scope.modificaCalendarioDiv = true;
$scope.successMessage = false;
$("#idModificaCalendarioDiv").hide();
$scope.element = new Calendario();
autoScroll('generaCalendario');
$("#idErrorTemplate").hide();
$('#data').attr('disabled', false);
$("#idGeneraCalendarioDiv").show();
};
Input :
<div class="col-xs-12 col-md-2" >
<label for="dataInizio" class="row col-xs-12 control-label" style="text-align: left">da Data</label>
<input class="datepicker form-control" placeholder="gg/mm/aaaa" required type="text" id="data" ng-disabled="true" />
</div>
Edit : forgot to add, the controller function is called by the button that displays the input for the calendar.
Because your factory's GET request will return the date value asynchronously, it's better to have a $scope.date in your controller that will hold the date value that is returned from the server. Also, depending on the format in which you store dates on the backend, you might need to transform the value that is returned from the backend into the string format, so it would be properly consumed by the <input type="date"> as per Angular docs.
In your code, you need to bind the input element to this value, like this: <input ng-model="date">.
What it will do is bind this input to the data model, so that every time when user edits the input the $scope.date would be updated too.
If you do not want users to be able to edit this date, then you need to:
Keep the input field disabled <input disabled> (no need to use ng-disabled here, because you want to keep it always disabled). And also remove this line: $('#data').attr('disabled', false); in your function.
You the one-way binding, instead of two0way binding, like this: <input disabled ng-value="date">
Here is the working DEMO that shows two inputs: one that is editable and another that is not.

How can I use user and password variables in my json request?

Pic 1: Angular 4
In the first picture I have my user input and I can display in the console variables username and password. In the second picture I am sending username and password with my token. How can I use the username and password from first picture and send those with my header? Please help.
Pic 2: json request
Headers class is constant so when you use it only is possible set headers while you are using new statement. i.e.
new Headers({header:value})
new Headers().append('header', 'value');
However this not work because is a constants
let headers = new Header();
headers.append('header','value')
You only can do thing as
new Headers({header:btoa(userna + ':' + password)});
HTML
<form #myForm="ngForm" (submit)="onSubmit(myForm)">
<input type="text" name="username">
<input type="password" name="password"
<input type="submit" value="Submit">
</form>
COMPONENT
onSubmit(form) {
if(form.valid) {
console.log(form.control.username);
console.log(form.control.password);
}
}
Ok if you are looking for your logins data, le proper way is to emit an event like this :
login-form component:
#output
onLogin : EventEmitter<any> = new EventEmitter();
login(e){
***
this.onLogin.emit({username:username,password:password});
}
app component.html
<login-form (onLogin)="getData($event)"></login-form>
here "$event" represent your object "{username:username,password:password}";
otherwise you can store datas in a variable and run "getData" when you want.
Other suggestions:
Use angular reactive-forms like this :https://angular.io/guide/reactive-forms#add-a-formgroup
maybe run your xhr from angular services.

How do i get input form value without submitting it?

I want the input value from user without submitting any thing then i want to pass it through ajax method as parameter to action method. I tried many method but i could not found a solution.
Here is the code
<input type="text" id="task" name="task" value="" />
#Ajax.ActionLink("ADD TASK", "show_task",new {task=Request["task"]}, new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "print",
InsertionMode = InsertionMode.Replace
})
Here is the controller action method
public ActionResult show_task(string task)
{
var add_task = new tasks_table();
add_task.task = task;
add_task.id = 24;
add_task.f_id=10;
add_task.date_oftask=DateTime.Now;
db.tasks_table.Add(add_task);
db.SaveChanges();
var tasks = db.tasks_table.Include(t => t.user_detail);
return PartialView("render_tasks",tasks);
}
Since you want the current value of the textbox, you may better do it yourself with your own javascript code to make the ajax call, instead of relying on the Ajax.ActionLink helper method.
So change your Ajax.ActionLink call to a normal action link.
<input type="text" id="task" name="task" value="" />
#Html.ActionLink("Add Task","show_task", null, new {id="addTask"})
<div id="print"></div>
Now listen to the click event on this link, read the value of the text box and send that to your server. You may use jQuery $.post method to do so. In the response callback, you can update the print div's content with the response coming back from your server.
$(function(){
$("a#addTask").click(function(e){
e.preventDefault();
$.post($(this).attr("href"), { task:$("#task").val()},function(res){
$("#print").html(res);
});
});
});
You can use JavaScript focusOut function to send the value to controller.
by focusOut method, we get the value in input field instantly when we moved to next field.
$('#task').focusOut(function(){
Your ajax call method....
});
Hopes it helps.

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();