I have my controller in Angular which contains an array and a delete method
function($scope, $http){
$scope.arrayOfObjects = [];
$scope.remove = function(obj){
var i = $scope.arrayOfObjects.indexOf(obj);
if( i > -1 ){
$scope.arrayOfObjects.splice(i, 1);
}
}
// Some other things
}
HTML
<a href ng-repeat="(key, obj) in arrayOfObjects track by $index">{{obj.id}}
<button type="button" role="button" class="btn btn-default" ng-click="remove(obj)">
<i class="fa fa-trash"></i>
<span>Delete</span>
</button>
</a>
Now all works well when I delete an object other than the last. When the user presses on the delete button for the last object, the page gets redirected to localhost:3000/# which is not mapped to anything and I get a blank page.
Has anyone encountered such behavior?
While the other answers are addressing your link / redirect issue, which would be solved by not having additional clickable items inside an anchor tag, the bigger problem is that you're using the wrong syntax for iterating over the objects of an array.
To iterate over an array you want this:
ng-repeat="obj in arrayOfObjects"
The syntax you're using is for iterating over the properties of one single object. Where key and value are the arguments passed to your repeater
ng-repeat="(key, value) in object"
Most likely what you want is something like this:
<div ng-repeat="obj in arrayOfObjects">
{{obj.id}}
<button ng-click="remove(obj)">Delete</button>
</div>
codepen
You can use 'filter' to return to original scope all itens that you want, just like that:
$scope.remove = function (objs) {
$scope.objs = objs.filter(function (obj) {
//Here you remove the item you do not want
return obj;
});
};
Html:
<button class="btn btn-danger btn-block" ng-click="remove(objs)">Delete</button>
Last element can be removed by using pop() and returns that element like $scope.arrayOfObjects.pop()
angular.module('app', [])
.controller('mycontroller', function($scope) {
$scope.arrayOfObjects = [{ id: 1 }, { id: 2 }, { id: 3 }]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="mycontroller">
<button ng-click="arrayOfObjects.pop()">remove in inline</button>
<ul>
<li ng-repeat="myobj in arrayOfObjects">{{myobj.id}}</li>
</ul>
</div>
Related
I am only posting the necessary code and solving this much will clear rest of my doubts. I am new to angularjs, so kindly forgive if I am asking something stupid.
I am using ng-repeat to generate a list which uses an array defined in the controller scope. When I click on 'Add Another' button, a new element is created. I want to get access of this element to add a class to it. But when I use 'getElementById' function in the same function 'addNewForm' I get 'null'.
However, when I call function 'fn' by hitting 'Find Untitled' button, I get the correct element. Could anybody explain and solve this? Any help is appreciated. Thanks in advance!
I am posting the code below:
HTML:
<div ng-controller="myctrl3">
<ul id ="menu_Ul">
<li ng-repeat="x in list">
<button id="{{ 'navAppsButtonID-' + $index }}">{{x}}</button>
<br>
</li>
<li>
<button ng-click="addNewForm()">Add another</button>
</li>
</ul>
<button ng-click="fn()">Find Untitled</button>
</div>
JS:
.controller("myctrl3", function($scope) {
var list = ['abcd', 'efgh', 'ijkl', 'mnop'];
$scope.list = list;
$scope.abc = function () {
var listPush = function () {
$scope.list.push("Untitled Menu");
for(var i = 0;i<$scope.list.length-1;i++) {
var element = document.getElementById('navAppsButtonID-'+i);
element.classList.remove('current');
}
};
var listLen = $scope.list.length;
if($scope.list[listLen-1] === undefined) {
listPush();
}
else if ($scope.list[listLen-1] == "Untitled Menu") {
alert("Cannot open more than one Untitled Menu at the same time.");
}
else {
listPush();
}
};
$scope.addNewForm = function() {
$scope.abc();
console.log("Element is: ", document.getElementById('navAppsButtonID-'+($scope.list.length-1)));
};
$scope.fn = function () {
console.log("Element is: ", document.getElementById('navAppsButtonID-'+($scope.list.length-1)));
};
})
You're thinking too much jQuery and too little angular. If the goal is to add a class to the last element of ng-repeat, this is how you do that:
<li ng-repeat="x in list">
<button ng-class="{ current: $last }">{{ x }}</button>
</li>
$last is a variable available inside ng-repeat, and if it's true, ng-class will set the class current on the element.
You don't assign unique ids to elements to getElementById from somewhere else when working in angular.
currently I'm extending my application, so I can give a directive (which generates a table grid) an object for additional buttons to show (for adding other other actions).
Now I can show the button but I need to execute some code as function which should be apply for a click on that button.
The object itself contains strings and function in a mixed way, like this:
<tablegrid
table="flavorings"
additional-buttons="[{name: 'add', onclick: 'function(){ }', icon: 'fa fa-plus'}]"
show-actionbutton="true"
show-rating="true"
show-search="true"
show-rowcheckbox="true"
show-header="true">
</tablegrid>
My directive template looks like this:
<button ng-repeat="aB in additionalButtons" class="btn btn-primary" ng-click="ab.onclick" type="button">
<i ng-class="aB.icon" ng-show="aB.icon != ''" aria-hidden="true"></i>
<span>{{ 'TABLEGRID_'+aB.name | uppercase | translate }}</span>
</button>
How can I execute the onclick-function?
You can directly call a function of an object of the scope in your view with:
ng-click="yourObject.functionName(parameters)"
Don't forget the parenthesis in the function call even if there is no parameters
Here is a demo of how it works:
var app = angular.module('myApp', []);
app.controller('MyCtrl', function($scope) {
$scope.additionalButtons = [
{'name': 'First',
'onclick': function() {alert('1')}
},
{'name': 'Second',
'onclick': function() {alert('2')}
}
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<button ng-repeat="ab in additionalButtons" ng-click="ab.onclick()">Click {{ab.name}}</button>
</div>
I'm using angularJS to build a SPA. I am trying to delete an object from an array in my controller. I am using ng-repeat and can't seem to get my head around this. Here is the related html:
<div class="cat-button" ng-repeat="category in cats" category="category">
<button class=" close-button" ng-click="removeCat()">
<span class="glyphicon glyphicon-remove-sign" aria-hidden=true> </span> </button>{{category.name}}
</div>
This created a div with a button for every object that gets saved to my $scope.cats array. It works fine but I cant figure out how do I use the button in each div to delete that specific object.
When I click on the button , the function on my controller gets called, but this is where I get lost, how do I delete the specific object created dynamically by the user.
This is the related code on my controller:
//Function to delete category
$scope.removeCat = function () {
//I know I have to use splice on my array but how do I Identify the object that needs to be deleted from my array?
};
You can either pass on $index like so:
<button class=" close-button" ng-click="removeCat($index)">
and in your function:
$scope.removeCat = function (index) {
$scope.cats.splice(index,1);
}
or pass the whole item and use indexOf (the saver way)
<button class=" close-button" ng-click="removeCat(category)">
$scope.removeCat = function (item) {
$scope.cats.splice(myArray.indexOf(item), 1);
}
You can pass the index of the item you want to delete in the ng-click function:
<div class="cat-button" ng-repeat="category in cats" category="category">
<button class=" close-button" ng-click="removeCat($index)">
<span class="glyphicon glyphicon-remove-sign" aria-hidden=true> </span> </button>{{category.name}}
</div>
Then you can use this in your Angular controller like this:
$scope.removeCat = function (index) {
$scope.cats.splice(index, 1);
};
Update
Incase you don't want to pass in the index, instead you can also pass in the entire object and locate the index in your controller. The code below is setup to work on all browsers. (Just haven't tested it ;) )
$scope.removeCat = function (cat) {
// Using underscore
var index = _.indexOf($scope.cats, cat);
// Or using a for loop
for(var i = 0; i < $scope.cats.length; i++) {
//Assuming your cat object has an id property
if($scope.cats.id === cat.id) {
index = i;
break;
}
}
};
Or any other way to locate the index of an object in an array.
ng-click="removeCat(category)"
$scope.removeCat = function (categoryToDelete) {
var index = $scope.cats.indexOf(categoryToDelete);
$scope.cats.splice(index, 1);
};
My data in Firebase looks like this...
evalu8er
situations
-K6rM12D-0nt4fJH_QcA
situation: "Test"
-K6rPoHiUl2N2JOSWXww
situation: "Test2"
-K6rPqbkBHJ-K8znVzay
situation: "Test3"
I have inserted the data from an HTML page via a form like this...
<div class="form-group">
<label for="situation">Add a situation</label>
<input type="text" class="form-control" id="situation" placeholder="Situation" ng-model="situation">
</div>
<button type="submit" class="btn btn-default pull-right" ng-click="add_situation()"><i class="fa fa-cog fa-spin" ng-show="loading"></i> Add </button>
</form>
The above form is calling the controller...
app.controller("situations", ["$scope", function ($scope) {
$scope.add_situation = function () {
var situation = $scope.situation;
var ref = new Firebase("https://evalu8er.firebaseio.com/situations");
ref.push().set({
situation: situation
});
};
}
]);
Now I want to get each of the situations back to the page, and this where it all goes wrong for me.
Inside the same controller as above I'm adding this....
var ref = new Firebase("https://evalu8er.firebaseio.com/user/situations/");
ref.on("value", function(snapshot) {
$scope.display_situatoins = snapshot.val();
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
And on the HTML page I have added
<li data-ng-repeat="x in display_situatoins">
{{ x }}
</li>
When the page loads it DOES NOT show me the data until I enter something in the form field,
Question 1/3)
How do I get the data to show on page load?
When it does load it looks like this...
{"situation":"Test"}
{"situation":"Test2"}
{"situation":"Test3"}
And what I want is just to show a list of the situations like this..
Test
Test2
Test3
Question 2/3)
How do I just show the situation values as above?
And when I do add a new item it gets listed at the bottom, how do I order the list with the new items at the top?
Question 3/3)
How do I order the list so the new items appear first?
Use AngularFire for synchronized collections.
angular.module('app', ['firebase'])
.constant('FirebaseUrl', '<my-firebase-app>')
.service('rootRef', ['FirebaseUrl', Firebase])
.controller('MyCtrl', MyController);
function MyCtrl($scope, rootRef, $firebaseArray) {
$scope.situations = $firebaseArray(rootRef.child('situations');
}
Then in your template for MyCtrl, you can do an ng-repeat on the situations array.
<li ng-repeat="situation in situations">
{{ situation.situation }}
</li>
The {{ situation.situation }} part looks awkward because of the naming. If you change the property situation to something like text or title it would look like:
<li ng-repeat="situation in situations">
{{ situation.title }}
</li>
I'm using Angular to repeat all these ids in an array but limit it to showing one at time like this:
<div ng-repeat="id in ids | limitTo:1">
{{array.id}}
</div>
I then want to have a div that when clicked will show the next id in the array, so basically increases the $index by one. Maybe something like...
<div ng-repeat="id in ids | limitTo:1">
{{array.id}}<br />
<div ng-click="$index + 1"></div>
</div>
The code above doesn't work so I can only surmise that I am going about this the wrong way. What's the right way to do this in Angular?
If you only want to show a single element at a time, there's no need to use an ng-repeat. You can just do something like this in your controller:
$scope.index = 0;
$scope.arr = ['your', 'array'];
$scope.increment = function() {
$scope.index = ($scope.index + 1) % $scope.arr.length;
};
And then in your view:
<div>
{{arr[$index].id}}<br />
<div ng-click="increment()"></div>
</div>
Well I think we cannot do that by increment $index as limitTo 1 says index is always zero
<button ng-click="onClick()">click here</button>
and onClick
$scope.onClick = function(){
//$index + 1
$scope.ids.shift();
}
Here is the plunker
http://plnkr.co/edit/A1VrbUoIPLhuA78CF4DM?p=preview
Demo FIDDLE
You only need to use ng-click and ng-init if you want to go through your ID array one by one:
In your view:
<div ng-controller="MyCtrl">
<button ng-click="index = index + 1" ng-init="index=0">
Next ID
</button>
ID: {{ids[index]}}
</div>
In your script file:
var myApp = angular.module('myApp',[]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
$scope.ids = [11, 21, 31, 41, 51]; //test array
}
Edit: you should also either disable the button when index >= arrayLength or reset the value of index to 0.