how to add elements into a form by using ng-click? - javascript

I have a form that has 4 fields
<form name="form">
Name:
<input type="text" ng-model="edit.name"><br />
age:
<input type="text" ng-model="edit.age"><br />
phone:
<input type="text" ng-model="edit.phone"><br />
address:
<input type="text" ng-model="edit.address"><br />
</form>
And i have an array in the app.js
$scope.statuses = [
{value: 1, text: 'status1'},
{value: 2, text: 'status2'},
{value: 3, text: 'status3'},
{value: 4, text: 'status4'}
];
I am repeating that array in the html and what i want to do is that i want the text to appear in the form when a button such as "edit" is clicked
PLUNKER
So basically as you can see in the plunker when i click on the edit button i want "status1" "status2" "status3" "status4" to appear in the fields that are in the form "name" "age" "phone" and "address"

Your question was a bit unclear, but I think what you want to do is change statuses to the form values.
I create this plunker for you
on your ng-click function. I change the statuses array text (which is shown with ng-repeat in your html) to your forms edit values:
$scope.editFunction = function(edit){
$scope.statuses[0].text=edit.name;
$scope.statuses[1].text=edit.age;
$scope.statuses[2].text=edit.phone;
$scope.statuses[3].text=edit.address;
};
or if you want your array values be in your form just reverse the = in your function like plunker :
but in this case,if you want your empty form to work, you should declare edit before in your controller.
$scope.edit=[];
$scope.editFunction = function(edit){
edit.name=$scope.statuses[0].text;
edit.age=$scope.statuses[1].text;
edit.phone=$scope.statuses[2].text;
edit.address=$scope.statuses[3].text;
};
and so you are using ng-model.there is no need to pass argument to your function, you can use $scope.edit instead of a passing argument in your editFunction

Related

how can I do "twoDataBinding" with formControlName? similar with ng Model

I'm setting a model with form, but I have a problem to set a "MyModel" with a form
This is for the purpose of optimizing the handling of the forms
public myModel = new MyModel();
this.myForm = this.formBuilder.group({
firstName: new FormControl({
value: this.myModel.firstName,
disabled: false
}),
middleName: new FormControl({
value: this.myModel.middleName,
disabled: false
}),
lastName: new FormControl({
value: this.myModel.lastName,
disabled: false
}),
age: new FormControl({
value: this.myModel.age,
disabled: false
})
});
when I submit a "submit" with a button, that shows me the "this.myForm" with the elements that I added in the form
but it seems that I would not be establishing a connection as a "TwoDataBinding"
I also do not want to do this code since I see it very redundant
also
when it comes to many forms and even worse if you decide to change or refactor the attributes of that object
this.myModel.firstName = this.myForm.controls['firstName'].value;
this.myModel.lastName = this.myForm.controls['lastName'].value;
this.myModel.middleName = this.myForm.controls['middleName'].value;
this.myModel.age = this.myForm.controls['age'].value;
You can see the complete code here:https://stackblitz.com/edit/form-model-hammer
of a form model, if you want to make changes makes a FORK to share, thanks:
also for the purpose of avoiding this alert in the picture
If you want to use 2-way binding, you should use template-driven forms instead. It allows you to use ngModel to create two-way data bindings for reading and writing input-control values.
The principles of reactive forms follows the 'one-way' rule, whereby you follow an immutable method of managing the state of your forms, such that there is greater separation of concern between your template and component logic. You can read more about the advantages of reactive forms on the above link.
If you think reactive forms is not what you want, you should revert to using template driven forms, as stated on the first paragraph.
One thing to take note, you should not use ngModel with reactive forms, as this will defeat the purpose of immutability.
However, if you are planning to stick to using reactive forms, you can simplify your code by doing this instead:
1) Initialising and declaring your reactive forms.
this.myForm = this.formBuilder.group({
firstName: [{value: this.myModel.firstName, disabled: true}],
middleName: [this.myModel.middleName],
lastName: [this.myModel.Name],
age: [this.myModel.age],
});
2) Get reactive form data:
// since the properties of myModel and myForm FormControl names are the same
this.myModel = {...this.myForm.value};
3) Update reactive form data:
this.myForm.patchValue(this.myModel);
You should stop using ngModel with Reactive forms as it is deprecated now .
You can simplify the code like below :
this.myModel.firstName= 'FIRST NAME';
this.myForm = this.formBuilder.group({
firstName:[{
value: this.myModel ? this.myModel.firstName : '',
disabled: false
}],
middleName: [{
value: this.myModel ? this.myModel.middleName : '',
disabled: false
}],
lastName: [{
value: this.myModel ? this.myModel.lastName : '',
disabled: false
}],
age:[{
value: this.myModel ? this.myModel.age : '',
disabled: false
}]
});
Listen to (ngOnSubmit) event and write a function to save the form values .
This can be achieved in the below way :
save(myForm : any){
let form = myForm as MyModel;
console.log(form);
form.otherProperties = 'nothing';
}
Or :
save(myForm : MyModel){
let form = JSON.parse(JSON.stringify(myForm)); //for copy
console.log(form);
form.otherProperties = 'nothing';
console.log( 'added a new property', form);
}
And in your html :
<div>
<form [formGroup]="myForm" (ngSubmit)='save(myForm.value)'>
<label>
<span>
Fisrt name:
</span>
<input type="text" formControlName="firstName">
</label>
<label>
<span>
Middle name
</span>
<input type="text" formControlName="middleName">
</label>
<label>
<span>
Last name
</span>
<input type="text" formControlName="lastName">
</label>
<label>
<span> Age: </span>
<input type="number" formControlName="age">
</label>
<div style="display: block">
<button (click)="onShowModel()">
show model
</button>
</div>
<div style="display: block">
<button>
set model from form
</button>
</div>
</form>
</div>
<div>
<p class="red"> from model : </p>
<span class="red"> Model: {{myModel | json}} {{nothing}}</span>
</div>
<div>
<p class="blue"> from form, binding model : </p>
<span class="blue"> Model: {{myForm.value | json}}</span>
</div>
I have also forked your example : Example

Using expression in ngmodel in angular 1.2

I am trying to show checkboxes checked or unchecked based on certain condition. for eg:
$scope.userRoles = {"grants" : [
"Permission",
"View",
"Update",
"Delete"
]}
On the HTML part i have added the following code:
<div ng-repeat="p in userRoles">
<input type="checkbox" ng-model="p.grants.indexOf('Delete') != -1?true:false" ng-change="AddRemovePermission(p,'Delete')" />
</div>
If i use ng-checked instead of ng-model than it works fine, but i will not get 2 way binding with that. Also i know we cant use expressions like above in ng-model.
Can anybody help on how this can be done. The only condition is if user has grants than the checkbox should be checked else not, and when clicked on checkbox it should be changed to checked or unchecked accordingly and gets added in the userRoles object. Cant use directive as well.
Thanks.
The problem is your model. You must send boolean to backend, this can be a solution:
In view:
<div ng-repeat="role in userRoles.grants">
<input type="checkbox" ng-model="role.checked" />
</div>
And in controller:
$scope.userRoles = {"grants" : [
{"permission": "Permission", checked: true },
{"permission": "View", checked: false },
{"permission": "Update", checked: true },
{"permission": "Delete", checked: true }
]}

Strange behaviour Angular driven select list

According to paper "How to set the initial selected value of a select element using Angular.JS ng-options & track by" by #Meligy which I used as a guidance to learn and solve my problem with implementing a select list (ng-options), I still encounter some strange collaterale behaviour.
Although the basic behaviour finally does what it should do, see Test Plunk, I still encounter strange behaviour on the selected item in that list. Not in my test plunk though, implemented in my developement site.
app.controller("TaskEditCtrl", function($scope) {
$scope.loadTaskEdit = loadTaskEdit;
function loadTaskEdit() {
taskLoadCompleted();
tasktypesLoadCompleted();
}
function taskLoadCompleted() {
$scope.tasks = [{
Id: 1,
Name: "Name",
Description: "Description",
TaskTypesId: 4
}
];
$scope.current_task_tasktypesid = $scope.tasks[0].TaskTypesId;
}
function tasktypesLoadCompleted() {
var tasktypes = [{ Id: 1, Name: "A" },
{ Id: 2, Name: "B" },
{ Id: 3, Name: "C" },
{ Id: 4, Name: "D" }];
$scope.available_tasktypes_models = tasktypes
}
$scope.submit = function(){
alert('Edited TaskViewModel (New Selected TaskTypeId) > Ready for Update: ' + $scope.tasks[0].TaskTypesId);
}
loadTaskEdit();
});
HTML
<form class="form-horizontal" role="form" novalidate angular-validator name="editTaskForm" angular-validator-submit="UpdateTask()">
<div ng-repeat="task in tasks">
<div>
<select ng-init="task.TaskTypes = {Id: task.TaskTypesId}"
ng-model="task.TaskTypes"
ng-change="task.TaskTypesId = task.TaskTypes.Id"
ng-options="option_tasttypes.Name for option_tasttypes in available_tasktypes_models track by option_tasttypes.Id">
</select>
</div>
</div>
<div class="">
<input type="submit" class="btn btn-primary" value="Update" ng-click="submit()" />
</div>
</form>
As said, see my test plunk which shows exactly what it supposed to do. Moreover, using 5 self-explaining images, I do hope to make my troulbe bit clearer what's the problem.
I'm a bit lost to figure out what's so troublesome. My 'water' is telling me something wrong or missing in css. Did have anybody out their ever have face comparable? What could cause me this trouble? Does have anybody out there have a clue?
Thanks in advance
[1
[]2
[]3
[]4
Apparently I'm a rookie on css. Any suggestion is welcome!
CSS
#region "style sheets"
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/css/site.css",
"~/content/css/bootstrap.css",
"~/content/css/bootstrap-theme.css",
"~/Content/css/font-awesome.css",
"~/Content/css/morris.css",
"~/Content/css/toastr.css",
"~/Content/css/jquery.fancybox.css",
"~/Content/css/loading-bar.css"));
#endregion "style sheets"
The key with the dropdown is to set the model to the object that was selected. I updated your code to behave the way that I believe you are asking for it to work.
The key differences are:
Set the ng-model of the dropdown to the selected object and not the id of the selected item. This will give you access to the full selected object and all it's properties.
Remove the ng-change binding - this is not necessary with 2 way data binding, and the value on the model (whatever is put in for ng-model) will automatically be updated.
In your HTML you were using properties that were never declared in the Controller $scope. I updated those to reflect the available variables that were in scope.
For more information on dropdowns please see the angular documentation. It's very useful for figuring these types of issues out - https://docs.angularjs.org/api/ng/directive/select
// Code goes here
var app = angular.module("myApp", []);
app.controller("TaskEditCtrl", function($scope) {
$scope.tasks = {};
$scope.current_task_tasktypesid = null;
$scope.selected_task_tasktype = null;
$scope.loadTaskEdit = loadTaskEdit;
function loadTaskEdit() {
taskLoadCompleted();
tasktypesLoadCompleted();
//EDIT: DEFAULT DROPDOWN SELECTED VALUE
$scope.selected_task_tasktype = $scope.available_tasktypes_models[2];
}
function taskLoadCompleted() {
$scope.tasks = [{
Id: 1,
Name: "Name",
Description: "Description",
TaskTypesId: 4
}
];
$scope.current_task_tasktypesid = $scope.tasks[0].TaskTypesId;
}
function tasktypesLoadCompleted() {
var tasktypes = [{ Id: 1, Name: "A" },
{ Id: 2, Name: "B" },
{ Id: 3, Name: "C" },
{ Id: 4, Name: "D" }];
$scope.available_tasktypes_models = tasktypes
}
$scope.submit = function(){
alert('submitted model: ' + $scope.selected_task_tasktype.Id);
}
loadTaskEdit();
});
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#*" data-semver="1.2.9" src="http://code.angularjs.org/1.2.9/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="myApp" ng-controller="TaskEditCtrl as edit">
<form class="form-horizontal" role="form" novalidate angular-validator name="editTaskForm" angular-validator-submit="UpdateTask()">
<div ng-repeat="task in available_tasktypes_models">
<div>Task (Id): {{task.Id}}</div>
<div>Name: {{task.Name}}</div>
<div>Descripton: {{task.Description}}</div>
</div>
<p>Current Task.TaskTypesId: {{selected_task_tasktype.Id}}</p>
<div>
<select
ng-model="selected_task_tasktype"
ng-options="option_tasttypes.Name for option_tasttypes in available_tasktypes_models track by option_tasttypes.Id">
</select>
</div>
<p>{{task.TaskTypes}}</p>
<p>{{selected_task_tasktypesid = task.TaskTypes}}</p>
<div class="">
<input type="submit" class="btn btn-primary" value="Update" ng-click="submit()" />
</div>
</form>
</body>
</html>
First, I need to state the implementation of #Meligy and the suggested input of 'dball' are correct. So, go with the flow of your choice.
Keep notice on your style sheets.
Finally, I figured out that the style property 'color' with the value 'white' of selector #editTaskWrapper as identifier of the parent
<div id="editTaskWrapper">
acted as the bad guy. One way or the other, if I comment 'color: white' in
#editTaskWrapper {
background-color: #337AB7;
/*color: white;*/
padding: 20px;
}
the selected item in the selectlist becomes visible. All other controls and values are not affected, only the selected list item.

select - populate when editing post

I have my angularjs view in wich I must populate my select box with value saved in database, and to allow for other options to be selected. I have tryed like this:
<div class="form-group">
<label class="control-label" for="status">Status zaposlenika</label>
<div class="controls">
<select required name="status" class="form-control" ng-model="employee.status" ng-options="statusType.name for statusType in statusTypes" >
</select>
</div>
But my value is not populated in my view. ( {{employee.status}} - > "test" )
$scope.statusTypes = [
{
name: 'test'
},
{
name:'Test1'
},
{
name: 'Test2'
},
{
name:'Test3'
}
];
How can I do this ?
EDIT
My model employee.status is populated with value "test". But my select box is not. Othe values are listed as items for selection. How can I set default value that is saved in my database to be pre-selected in my select box.
Your model employee.name is a string and selectbox is bound to an object similar to {name: "Test1"}. So if you want to select option from statusTypes you have to find corresponding object in array of object.
$scope.statusTypes = [
{name: 'Test1'},
{name: 'Test2'},
{name: 'Test3'}
];
var selectedStatus = $scope.statusTypes.filter(function(type) {
return type.name = 'Test2';
})[0];
$scope.employee = {
status: selectedStatus
};
So you have to make employee.status to be one of the objects from statusTypes array.
Or other option is to continue to use string for employee.status and change ngOptions to bind to a string instead of object:
ng-options="statusType.name as statusType.name for statusType in statusTypes"

How can I update a list of checkboxes via Ajax without unchecking them

Consider the following list of checkboxes - a list of online and a list of offline users;
<h1>Users</h1>
<div id="users">
<h2>Online</h2>
<ul>
<li><input type="checkbox" name="userId[]" value="1" /> Joe Bloggs</li>
<li><input type="checkbox" name="userId[]" value="2" /> Bill Gates</li>
<li><input type="checkbox" name="userId[]" value="3" /> John Smith</li>
</ul>
<h2>Offline</h2>
<ul>
<li><input type="checkbox" disabled="disabled" name="userId[]" value="4" /> The Queen</li>
<li><input type="checkbox" disabled="disabled" name="userId[]" value="5" /> Steve Jobs</li>
</ul>
</div>
The user can check the online users and then perform an action such as sending them (1 or more) an email - but I need the list to update dynamically as users log in and out of the system.
The code I am using to update the list every 20 seconds or so is something like this;
$("#users").load("/path/to/my/users/load.php");
but obviously this simply replaces the HTML in the "users" div and un-checks any "online" boxes that were checked by the user (which is annoying if the user hasn't yet performed the action).
So in short; I'm struggling to write the necessary code in jQuery that can fetch a list of online and offline users, add/remove them from the lists while keeping the checked values intact in the "online" list.
1) Wrap your lists in a form
2) Serialize the selected checkboxes
3) Perform your DOM replacement
4) Iterate through the selected checkboxes and reapply them
var checked = $('#users form').serializeArray();
//perform ajax call
//in the ajax success function after replacing the DOM
$.each(checked, function(i, data) {
$('input[name="'+data.name+'"][value="'+data.value+'"]').attr('checked', 'checked');
});
Take a different approach: instead of .load(), use, say, $.getJSON() to retrieve an object which looks like:
{
online: [
{id: 1, name: 'Joe Bloggs'},
{id: 2, name: 'Bill Gates'},
{id: 3, name: 'John Smith'}
],
offline: [
{id: 4, name: 'The Queen'},
{id: 5, name: 'Steve Jobs'}
]
}
and update HTML yourself, using the existing checkbox if present for that user ID.
You could save in a global var when they are changed (onClick), and after the .load, using the callback/something else, recheck them.
Load the online/offline users using ajax, and move the elements around depending on their status. My take on this:
// Define all users
var allUsers = {users:[
{id: 1, name: 'Joe Bloggs'},
{id: 2, name: 'Bill Gates'},
{id: 3, name: 'John Smith'},
{id: 4, name: 'The Queen'},
{id: 5, name: 'Steve Jobs'}
]
};
// Define which users are online
var onlineUser = [2,3,5,12,76];
$.each(allUsers.users,function(id,user){
$('<input />').attr('type','checkbox').attr('name','userId[]').val(user.id).attr('disabled','disabled').appendTo($('<li />').text(user.name).appendTo($('#offline')));
});
// function to update which users are online
function reloadUsers(onlineUsers){
$('#online li input').attr('disabled','disabled').parent().appendTo($('#offline'));
$.each(onlineUsers, function(id,user){
$('#offline [value="'+user+'"]').attr('disabled',false).parent().appendTo($('#online'));
});
}
// load online users on document load
reloadUsers(onlineUser);
// just used in the text example to show how to update online users
$("#reload").click(function(){
reloadUsers($("textarea").val().split(","))
});
Example: http://jsfiddle.net/niklasvh/4zde9/

Categories