Angular: how to save edited values? - angularjs

here is my plnkr
http://plnkr.co/edit/0W1SZll1BOK5uuEtdycy?p=preview
im trying to save edited values from my edit contact modal.
here is a edit method that takes current value from object:
$scope.edit = function(terminal) {
$scope.name = terminal.name;
$scope.last = terminal.last;
$scope.age = terminal.age;
}
i read about angular copy, there is anything else?
any one can help me please ill glat to learn how to do that

Use angular.copy when assigning value of object or array to another variable and that object value should not be changed.
Without deep copy or using angular.copy, changing value of property or adding any new property update all object referencing that same object. Your JS will look like this:
$scope.edit = function(terminal) {
$scope.name = angular.copy(terminal.name);
$scope.last = angular.copy(terminal.last);
$scope.age = angular.copy(terminal.age);
}

You are creating a lot of extra manual work by not using one object in ng-model in the first place instead of using individual scope properties.
There is a golden rule also that if you don't have a dot in ng-model you are doing it wrong
Do something like:
<input ng-model="terminal.name">
<input ng-model="terminal.age">
Then work along the following lines:
$scope.edit = function(terminal) {
// store reference to terminal being edited
$scope.currentTerminal = terminal;
// make a copy so live one is not affected -- will be used in form
$scope.terminal = angular.copy(terminal);
}
$scope.save = function(){
// update stored original with changes
angular.extend($scope.currentTerminal, $scope.terminal);
// reset terminal used in form
$scope.terminal ={};
}
I would strongly suggest you get rid of jQuery and bootstrap.js and use angular-ui-bootstrap insted

You need to pass the index of the row that you are going to edit. pass the index when you click on edit button.
Change in script.js
$scope.edit = function(terminal,index) {
$scope.name = terminal.name;
$scope.last = terminal.last;
$scope.age = terminal.age;
$scope.edit_index = index
}
$scope.saveEdit =function(){
index = $scope.edit_index
$scope.terminals[index].name = $scope.name;
}
Change in index.html
<td> <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#editModalLong" ng-click="edit(terminal,$index)">Edit</button>
<button type="button" class="btn btn-primary" data-dismiss="modal" ng-click="saveEdit()">Save</button>
http://plnkr.co/edit/GpVB2dUiHCY6NslQDuBe?p=preview

Related

Get values into edit form angular

Inside main.view.html I have button Edit:
<md-button class="md-raised md-primary" ng-click="redirectEdit($index)" >Edit</md-button> which has redirectEdit($index) so it takes index of current line (to have values) in main.controller.js it looks like:
$scope.redirectEdit = function(index){
$scope.all[index];
window.location = "../ang/#!/edit";
$scope.name =$scope.all[index].name;
$scope.surname =$scope.all[index].surname;
$scope.email =$scope.all[index].email;
$scope.review =$scope.all[index].review;
};
with this method I want to redirect user to Edit form And have these specific taken entered into input fields.
First Name: <input type="text" ng-model="name" >
I tried doing it like this but that doesn't work
Looking at your scenario, i would suggest you to use $emit and $on.Also make a object of all fields like $scope.formFields = {};
$scope.redirectEdit = function(index){
$scope.all[index];
$scope.formFields = {};
$scope.formFields.name =$scope.all[index].name;
$scope.formFields.surname =$scope.all[index].surname;
$scope.formFields.email =$scope.all[index].email;
$scope.formFields.review =$scope.all[index].review;
$scope.$emit('userData', {data: $scope.formFields}); //to set the value
window.location = "../ang/#!/edit";
};
And on editController.js get the data and accordingly assign values to ng-model
$rootScope.$on('userData', function (event, data) {}); // to get the value
I hope this helps

ng-repeat only updating after clicking another tab or typing in a textbox

I'm pretty new to angular and have been having a bit of a problem in trying to create a basic "to-do" list sort of app.
There are various categories in the sidebar, and the user can click a button that brings up a modal prompting the user for the name of a new category. This name is used to create a new category, which is pushed onto the preexisting array.
However, the new category is only appearing after I start typing in another text-box on the screen or click on another tab.
The code that should be relevant:
var list = this;
$(document).on("click", ".prompt", function(e) {
bootbox.prompt("What do you want your new category to be?", function(result) {
if(result !== null) {
list.addCategory(result);
}
});
});
this.addCategory = function(result) {
if(result.trim() != "") {
var newCategory = new Category(result);
list.categories.push(newCategory);
this.setCategory(newCategory);
}
};
I can't seem to figure out how to post HTML as a code block, but here's the directives used to list out the categories (with categoryCtrl being the controller in question): ng-class="{active: categoryCtrl.isSet(category) }" ng-repeat="category in categoryCtrl.categories" ng-init="categoryCtrl.currCategory = categoryCtrl.categories[0]"
I know that the array is being updated immediately - if I add an alert 'bootbox.alert(list.categories[list.categories.length-1].name)' the alert gives me whatever the input was like it's supposed to. It's just not showing up in the ng-repeat.
Another interesting observations is that the ng-init overrides the this.setCategory(newCategory) - so it seems that when the list does update, it is reverting to its ng-init value.
Other places where I have an ng-repeat of an array, it's updated automatically when something new is pushed onto it. I'm wondering if it may have something to do with the modal/usage of bootbox - everywhere else things are added either by a checkbox or keying something into a textbox on screen, this is the only place where a modal is used.
Here is a working plunker based on your code.
The app looks like below. I initialize an array with dummy data for the example, but an empty array would work too. I used the vm = this syntax similar to what you have. When calling $nbBootbox.prompt it returns a promise so you need to use the then() syntax like below:
var app = angular.module('plunker', ['ngBootbox']);
app.controller('MainCtrl', ['$scope', '$ngBootbox', function($scope, $ngBootbox) {
var vm = this;
vm.name = 'World';
vm.categories = ['Category 1', 'Category 2'];
vm.prompt = function() {
$ngBootbox.prompt('Enter a new category?')
.then(function(result) {
console.log('Prompt returned: ' + result);
vm.categories.push(result);
}, function() {
console.log('Prompt dismissed!');
});
}
}]);
To make your HTML more angular like I changed it to this and also use the ControllerAs syntax:
<body ng-controller="MainCtrl as vm">
<p>Hello {{vm.name}} !</p>
<ul>
<li ng-repeat="c in vm.categories">{{c}}</li>
</ul>
Add Category
</body>
So, the link calls the prompt() function... it opens the modal and if you enter in the category, I push it to the categories array and it is added automatically to the page as a new bullet point in the list of categories.
From the documentation:
$ngBootbox.prompt(msg)
Returns a promise that is resolved when submitted and rejected if dismissed.
Example
$ngBootbox.prompt('Enter something')
.then(function(result) {
console.log('Prompt returned: ' + result);
}, function() {
console.log('Prompt dismissed!');
});
Hope this helps. let us know.

Add new entry to (empty) scope array using ng-click directive

My scope does not contain an "notYetExistingArray" at the time of generation.
Via a button, I would like to add the array plus a first entry to it.
Each subsequent push of the same button should then add another entry.
Unfortunately, I have no clue on how to approach it.
Currently I have:
<button type="button" ng-click="notYetExistingArray.unshift({})">
If the scope already contains an object "notYetExistingArray" of type array = [] I can easily add an entry with above function.
Any advise on how to do it?
Call a controller function from your ng-click directive rather than trying to do all that stuff in your markup. It can include a check for the existence of the array, and create it if needed.
<button type="button" ng-click="addThis(thing)">
In the controller:
ctrl.addThis = function(thing) {
if (ctrl.myArray === undefined) {
ctrl.myArray = [];
}
myArray.unshift(thing);
};
Note that I'm using controllerAs syntax here, so ctrl might be $scope instead.
You can initialize the array before doing that, for example:
<button type="button" ng-init="notYetExistingArray=[]" ng-click="notYetExistingArray.unshift({})">
check the documentation for ng-init https://docs.angularjs.org/api/ng/directive/ngInit
A good way is to bind a function on the ngClick directive, which will perform a test in order to check if the array exist.
In your controller :
function foo(item) {
//if my array does not exist
if (!$scope.myArray) {
//create the array
$scope.myArray = [];
}
//Here, we can add some data to our array, we are sure that the array exist
$scope.myArray.unshift(item);
}
$scope.foo = foo;
Html :
<h2>Array.length : {{myArray.length}}</h2>
</br>
<button type="button" ng-click="foo({})">Add</button>
Feel free to check the Working Plunker

FirebaseArray changing $id? [duplicate]

Here is the relevant code in my view:
p(ng-repeat="t in todos")
input(
type="checkbox",
ng-model="t.done",
ng-click="clearItem($event)"
)
{{t.text}} done? {{t.done}}
When the checkbox is clicked, I want the appropriate object in the todos array to be removed from the database.
My clearItem function is as follows:
$scope.clearItem = function(event) {
todoRef.remove($scope.t);
}
However, this removes all the entries in my database. I want it to remove only the specific object in question. Is there anyway for me to do this?
Ok, figured it out.
When looping using ng-repeat, use (id, t) in todos. This allows you to send id as the parameter to the ng-click function, and $scope.todos.$remove(id) works just fine.
To provide a more complete example for anyone else that lands here, according to Firebase's documentation for AngularFire this would be the preferred way, and I believe the easiest way to remove an object:
// Create an app. Synch a Firebase array inside a controller
var myApp = angular.module("myApp", ["firebase"]);
// inject $firebaseArray
myApp.controller("TodoCtrl", ["$scope", "$firebaseArray", function($scope, $firebaseArray) {
// bind $scope.todos to Firebase database
$scope.todos = $firebaseArray(myFirebaseRef.child("todo"));
// create a destroy function
$scope.removeTodo = function(todo) {
$scope.todos.$remove(todo);
};
}]);
In your view, you could do something like below. Note that you could bind the removeTodo function to a checkbox as the question specifies, or a regular old <a href> element:
// In your view
<div ng-controller="TodoCtrl">
<ul>
<li ng-repeat="todo in todos">
{{ todo.text }} : <a href ng-click="removeTodo(todo)">X</a>
</li>
</ul>
</div>
Hope that helps!
A better solution would be to have $scope.clearItem() take the object t as an argument, instead of $event.
HTML - <p ng-repeat="t in todos"><input... ng-click="clearItem(t)">
JS - $scope.clearItem = function(obj) {todoRef.$remove(obj)};
The only way I'm able to remove the item is using a loop on the array we get from firebase.
var ref= new Firebase('https://Yourapp.firebaseio.com/YourObjectName');
var arr_ref=$firebaseArray(ref);
for(var i=0;i<arr_ref.length;i++){
if(key==arr_ref[i].$id){
console.log(arr_ref[i]);
arr_ref.$remove(i);
}
}
The easiest way to remove the object would be
scope.clearItem = function(event) {
todoRef.$loaded().then(function(){
todoRef.$remove($scope.t)
});
The asynchronous nature of the beast has gotten me a few times.

AngularFire - Remove Single Item

Here is the relevant code in my view:
p(ng-repeat="t in todos")
input(
type="checkbox",
ng-model="t.done",
ng-click="clearItem($event)"
)
{{t.text}} done? {{t.done}}
When the checkbox is clicked, I want the appropriate object in the todos array to be removed from the database.
My clearItem function is as follows:
$scope.clearItem = function(event) {
todoRef.remove($scope.t);
}
However, this removes all the entries in my database. I want it to remove only the specific object in question. Is there anyway for me to do this?
Ok, figured it out.
When looping using ng-repeat, use (id, t) in todos. This allows you to send id as the parameter to the ng-click function, and $scope.todos.$remove(id) works just fine.
To provide a more complete example for anyone else that lands here, according to Firebase's documentation for AngularFire this would be the preferred way, and I believe the easiest way to remove an object:
// Create an app. Synch a Firebase array inside a controller
var myApp = angular.module("myApp", ["firebase"]);
// inject $firebaseArray
myApp.controller("TodoCtrl", ["$scope", "$firebaseArray", function($scope, $firebaseArray) {
// bind $scope.todos to Firebase database
$scope.todos = $firebaseArray(myFirebaseRef.child("todo"));
// create a destroy function
$scope.removeTodo = function(todo) {
$scope.todos.$remove(todo);
};
}]);
In your view, you could do something like below. Note that you could bind the removeTodo function to a checkbox as the question specifies, or a regular old <a href> element:
// In your view
<div ng-controller="TodoCtrl">
<ul>
<li ng-repeat="todo in todos">
{{ todo.text }} : <a href ng-click="removeTodo(todo)">X</a>
</li>
</ul>
</div>
Hope that helps!
A better solution would be to have $scope.clearItem() take the object t as an argument, instead of $event.
HTML - <p ng-repeat="t in todos"><input... ng-click="clearItem(t)">
JS - $scope.clearItem = function(obj) {todoRef.$remove(obj)};
The only way I'm able to remove the item is using a loop on the array we get from firebase.
var ref= new Firebase('https://Yourapp.firebaseio.com/YourObjectName');
var arr_ref=$firebaseArray(ref);
for(var i=0;i<arr_ref.length;i++){
if(key==arr_ref[i].$id){
console.log(arr_ref[i]);
arr_ref.$remove(i);
}
}
The easiest way to remove the object would be
scope.clearItem = function(event) {
todoRef.$loaded().then(function(){
todoRef.$remove($scope.t)
});
The asynchronous nature of the beast has gotten me a few times.

Resources