Adding button functionality individually in angularjs template - angularjs

I have a template. In the template, there are three boxes. Each box has add button, which will add an input field in that box. I have tried the following codes.
HTML
<div class="row">
<div ng-repeat="item in items2">
<div class="theBox">
<button class="btn btn-success" ng-click="addItem()">add</button>
<h6>{{item.key}}</h6>
<input ng-model="item.value">
</div>
</div>
</div>
AngularJs
$scope.items2 = [
{
"key" : "a",
"value" : []
},
{
"key" : "b",
"value" : []
},
{
"key" : "c",
"value" : []
}
];
$scope.addItem = function(){
console.log("clicked ")
angular.forEach($scope.items2, function(mm){
mm.value.push({})
})
}
The Problem: If I click on add, it's creating an object inside each value, maybe because I have used the forEach-loop for each value. How can I add it individually?
Also The input tag is not added as well, how can I fix that ?

Your question it's not exactly clear.
If you are going to
add an input field in that box
every time you click on the add button, then you will need another ng-repeat in your HTML.
Something like:
<div class="row">
<div ng-repeat="item in items2">
<div class="theBox">
<button class="btn btn-success" ng-click="addItem(item)">add</button>
<h6>{{item.key}}</h6>
<input ng-repeat="itemValue in item.value" ng-model="itemValue.text">
</div>
</div>
and your javascript to:
$scope.addItem = function(item){
item.value.push({text:""});
}

which will add an input field in that box.
If I understand you right you want to add <input>s to specific box.
I would write something that:
<div class="row">
<div ng-repeat="item in items2">
<div class="theBox">
<button class="btn btn-success" ng-click="addItem(item)">add</button>
<h6>{{item.key}}</h6>
<div ng-repeat="value in item.values">
<input ng-model="value.text">
</div>
</div>
</div>
</div>
and method will be:
$scope.addItem = function(selectedItem){
selectedItem.values.push({text:""});
}
Demo Plunker
Tips:
If you have list og inputs, the good practice to name it values and
not value in {
"key" : "a",
"value" : []
},
input ng-model is based on string and not object so will be better to set {text:""} and <input ng-model="value.text">

Related

Two way binding in *ngFor on Array of elements(non-object)

I have a simple array tags = []; and I'm pushing blank element on addNew() using this.tags.push("");. It creates blank element in that array.
Now, I'm using this array to add multiple items to be added from the input
<div class="row tagEntry" *ngFor="let tag of tags, let i = index">
<div class="col-md-10">
<input type="text" name="tag-{{i}}" placeholder="Tag Name" [(ngModel)]="tag" class="form-control">
</div>
<div class="col-md-2">
<button class="btn btn-block btn-danger" (click)="removeTag(i)"><i class="fa fa-trash"></i></button>
</div>
</div>
My TS file:
todoDesc: string = '';
tags = [];
ngOnInit() {
}
addTag () {
this.tags.push("");
console.log(this.tags)
}
removeTag (index) {
this.tags.splice(index, 1);
}
addTodo () {
console.log(this.todoDesc, this.tags)
}
Issue here is, it is not binding the input and array two way. When I log the array after updating inputs, the array displays items with all blank value.
How to two way bind the array of elements in Angular 5 using *ngFor?
The issue is with Array whose changes are not being detected through reference. You can make the following changes -
html
<div class="row tagEntry" *ngFor="let tag of tags; let i = index; trackBy:trackIndex">
<div class="col-md-10">
<input type="text" placeholder="Tag Name" [(ngModel)]="tags[i]" class="form-control">
</div>
<div class="col-md-2">
<button class="btn btn-block btn-danger" (click)="removeTag(i)"><i class="fa fa-trash"></i></button>
</div>
</div>
ts
Add the following function in ts file. This function is very important otherwise the array will re-build the complete UI on any change and you will loose the focus from the elememt.
trackIndex(index,item){
return index;
}
Here is the working copy - https://stackblitz.com/edit/angular-pzdw6s

how to remove the value of an input field using angularjs

<div class="info-block" ng-app="">
<div ng-controller="Note">
<div class="checkbox">
<label>
<p><b>Primary Publication: </b>
{{ form_widget(form.input_ppubs, { 'attr': {'class': 'valOption'}}) }}
</p>
</label>
</div>
<div ng-repeat="item in items">
<input type="text" placeholder="new input" ng-model="item.primaryPub">
</div>
<button type="button" ng-click="add()">New Item</button>
</div>
I am trying to retrieve the value of the html input field and remove it from input upon a button click
I am able to get the code, but I don't know how to remove the code.
var Note = function($scope){
$scope.items = [];
$scope.add = function () {
//angular way of implementing document.getElementByID();
pub1 = angular.element('#form_input_ppubs').val();
$scope.items.push({
primaryPub: pub1
});
};
}
You don't have to retrieve your items like this. It's ugly and not the angular way. angular.element('#form_input_ppubs').val();
Instead, simply reference it in your input using ngModel.
Declare it in your scope.
$scope.inputItem = null;
HTML
<input ng-model="inputItem " />
Use it in your function:
$scope.addItem = function(item) {
$scope.items.push(item);
//reset the model
$scope.inputItem = null;
}
Call it using ng-click
<button type="button" ng-click="addItem(inputItem)">Add Item</button>
If you do:
console.log($scope.items);
You should see an entry for primaryPub, the model for your input. Then you can target it by nulling the model, so:
$scope.items.primaryPub = null;
However you're using this inside an ng-repeat:
<div ng-repeat="(i, item) in items">
<input type="text" placeholder="new input" ng-model="items[i].primaryPub">
</div>
So your console.log (if you have more than one item in 'items') should show an array-like structure for primaryPub.

ngModel checkbox not shown as selected

I'm having some trouble getting a checkbox to display the correct state (checked/unchecked) of my model. I have the following in my controller:
app.controller('PhotosCtrl', ['$scope', function($scope) {
$scope.form = {};
$scope.editPhotos = {
token: $scope.token,
idArray: $scope.idArray
};
}]);
My form looks like this:
<form accept-charset="UTF-8" name="editPhotosForm" ng-submit="submit(editPhotos);" multipart="true" novalidate>
<input name="utf8" type="hidden" value="✓">
<input name="authenticity_token" type="hidden" ng-model="editPhotos.token" ng-init="editPhotos.token='<%= form_authenticity_token %>'">
<div class="results-label"><b>{{total_count}}</b> <span ng-if="total_count == 1">Photo</span><span ng-if="total_count != 1">Photos</span> Found</div>
<div>
<div class="col">
<a ng-repeat="r in results" class="card result-link">
<div class="content result">
<div class="caption">
<input type="checkbox" ng-model="idArray[r.id]">
</div>
<div class="image-container" ng-style="{'background-image': 'url(' + r.image_url + ')'}">
</div>
</div>
</a>
</div>
</div>
</form>
On my repeater element, I call ng-init="idArray[r.id] = 'false'" to initialize a key r.id = 'false' for each item in r. I don't know if I need to do this or not. I've tried the code without it and it makes no difference. I've also tried using ng-value-true and ng-value-false but those don't seem to be working for me.
Most of the other posts I've seen on this issue deal with simple variables (e.g. $scope.someVar = true rather than more complex structures like a hash.
Here is the structure of idArray:
$scope.idArray = {1290: "false", 1291: "true", 1292: "true", 1293: "false", 1294: "false", 1414: "false"};
This is generated by the ng-init in my repeater, since the ids of the photos can't be known beforehand.
Here is what results looks like:
{
id: 1290,
company_id: null,
image_url: "http://s3.amazonaws.com/mybucket/photos/images/000/001/290/original/214.JPG?1432217895"
}
Doing the following
ng-init="idArray[r.id] = 'false'"
You're assigning the string value 'false' into your object.
Can't you deal with that inside your controller?
$scope.idArray = {};
for (var i = 0; i < $scope.results.length; ++i){
$scope.idArray[$scope.results[i].id] = (i%2 == 0);
}
And removing the ng-init="" (which is, according to Angular doc, a bad practice https://docs.angularjs.org/api/ng/directive/ngInit ).
Another thing was the anchor element that was wrapping the checkbox element. This lead to the click event that was not triggered on the checkbox, but only on the anchor.
<div class="col">
<div ng-repeat="r in results" class="card result-link">
<div class="content result">
<div class="caption">
<input type="checkbox" ng-model="idArray[r.id]">
</div>
<div class="image-container" ng-style="{'background-image': 'url(' + r.image_url + ')'}">
</div>
</div>
</div>
</div>
fiddle :
http://jsfiddle.net/patxy/wak7pwwp/

Angular JS binding scope data within ng-repeat to form

I have a collection of items in $scope.data with fields "id","name" & "age", that are being displayed in the view using ng-repeat directive.
For each set of items, there is a corresponding "edit button".
I want to be able to access values for the particular set of items for which edit button was pressed.
Html:
<div ng-controller="Ctrl">
<div ng-repeat="i in data">
Name: {{i.name}}
Age: {{i.age}}
<form ng-submit="submit()">
<input type="text" ng-model="i.id"/>
<input type="submit" value="Edit" />
</form>
</div>
</div>
Script:
function Ctrl($scope)
{
$scope.data = [
{id:1,name:"Alex",age:22},
{id:2,name:"Sam", age:28}
];
$scope.submit = function() {
//access id of user for which edit was clicked
};
}
What is the right way to do this?
Instead of a form, I would suggest you just use a button:
<div ng-controller="Ctrl">
<div ng-repeat="i in data">
Name: {{i.name}}
Age: {{i.age}}
<input type="text" ng-model="i.id"/>
<button ng-click="submit(i)">Edit</button>
</div>
</div>
Just send i into the button click event (I suppose you could use form if you need validation, but your example doesn't seem to need it).
Your submit function then changes to:
$scope.submit = function(selectedItem) {
// here you now have access to selected item
};
Try this:
HTML:
<form ng-submit="submit(i.id)">
JavaScript:
$scope.submit = function(userId) {
// you have userId
};
One option is to just use an ng-click within a button that calls your submit passing in i
<div ng-controller="Ctrl">
<div ng-repeat="i in data">
Name: {{i.name}}
Age: {{i.age}}
<button ng-click="submit(i);">edit</button>
</div>
</div>
and the function:
$scope.submit = function(i) {
console.log(i);
//access id of user for which edit was clicked
};
Here's a fiddle of that working: http://jsfiddle.net/pRAcP/

How to get Angular to have a click event bring part of the dom with it to the function?

I am creating a small practice to-do list app with Angular. I have created a form for creating new tasks and they are updating fine. I have a button generate for every task that is titled "remove". I'd like to make the button remove specifically that task from the todo list. Here's the html code:
<div ng-controller="todoListController">
<ul>
<li ng-repeat="task in taskList">
<p>
{{task.name}}: {{task.description}}
<button ng-click="killtodo()"> Remove </button>
</p>
</li>
<hr>
<h3> Display: </h3>
<li>
<p>
{{task}}: {{taskDescription}}
<p>
</li>
</ul>
<hr>
<form ng-submit="addto()">
<input type="text" ng-model="task" placeholder="Enter a task name.">
<input type="text" ng-model="taskDescription" placeholder="Enter the description.">
<input class="btn-primary" type="submit" value="add">
</form>
</div>
Javascript code:
function todoListController($scope) {
$scope.taskList = [
{"name": "Task List",
"description": "Make a Task List."}
];
$scope.addto = function() {
$scope.taskList.push({name:$scope.task, description:$scope.taskDescription});
$scope.task = '';
$scope.taskDescription = '';
};
$scope.killtodo = function(name) {
};
}
Any suggestions would be great, thanks.
You have access to a variable called $index while using an ng-repeat so you can do something like this:
<li ng-repeat="task in taskList">
<p>
{{task.name}}: {{task.description}}
<button ng-click="killtodo($index)"> Remove </button>
</p>
</li>
And then in your controller:
function todoListController($scope) {
//other code
$scope.killtodo = function($index){
$scope.taskList.splice($index, 1);
}
}
There's more description available in the docs at the top (including other variables you can use): http://docs.angularjs.org/api/ng.directive:ngRepeat

Resources