to update in ng-rpeat angularjs - angularjs

I want to update username in ng-repeat directive. I am able to edit if I take a variable but unable to do so in an array. Here title is a variable and users is an array. I want to update a user's name
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
<div ng-app>
<div ng-controller="ClickToEditCtrl">
<div ng-hide="editorEnabled">
{{title}} {{name}}
<br>users
<ul> <li ng-repeat="(key,u) in users">
{{key+1}} name: {{u.name}} Edit title
</li></ul>
</div>
<div ng-show="editorEnabled">
<input ng-model="editableTitle" ng-show="editorEnabled"><br><br>
<input ng-model="editableUserName" ng-show="editorEnabled">
Save
or
cancel.
</div>
</div>
</div>
<script>
function ClickToEditCtrl($scope) {
$scope.title = "Welcome to this demo!";
$scope.users = [{'name':'A'},{'name':'B'}];
$scope.editorEnabled = false;
$scope.enableEditor = function(name) {
$scope.editorEnabled = true;
alert(name);
$scope.editableTitle = $scope.title;
$scope.editableUserName = name
};
$scope.disableEditor = function() {
$scope.editorEnabled = false;
};
$scope.save = function() {
$scope.title = $scope.editableTitle;
$scope.users.name = $scope.editableUserName;
$scope.disableEditor();
};
}
</script>`
`

Ideally, you'd like to have an id which doesn't change that associates to each user.
This plunker is your answer plunker
I have gone and used the $index of the array as an id, but ideally you should give each user an id
ng-click="enableEditor($index)"
I have also altered some of your functions to record the index

For the edit pass in the user you are editing:
Edit title
Then store a reference to that user.
var editableUser;
$scope.enableEditor = function(user) {
$scope.editorEnabled = true;
$scope.editableTitle = $scope.title;
$scope.editableUserName = user.name;
editableUser = user;
};
Then in the save, save the changes to the user:
$scope.save = function() {
$scope.title = $scope.editableTitle;
editableUser.name = $scope.editableUserName;
$scope.disableEditor();
};
http://plnkr.co/edit/2VZk2Ej6DR4g51MjiC3j?p=preview

Related

Error while retrieving data from local storage

i am unable to retreive the data when i reopen my app.What should i do to permanently save the data
I tried this code:
<body ng-app="starter" ng-controller="Appctrl">
<form data-ng-submit="addTodo()" class="todo-form">
<input type="text" data-ng-model="todoText" placeholder="Enter new ToDo
item" />
<br />
<input type="submit" value="Add Task" />
</form>
<ul class="unstyled">
<li data-ng-repeat="item in todo track by $index">
<input type="text">
<span>{{ item.text }}</span>
</li>
</ul>
</body>
and in app.js:
.controller("Appctrl", function($scope) {
$scope.addTodo = function() {
$scope.text = $scope.todoText;
$scope.todos = [];
$scope.todo.push(text);
$scope.todoText = ''; //clear the input after adding
localStorage.setItem('todo', JSON.stringify($scope.todo));
$scope.saved = localStorage.getItem('todo');
localStorage.setItem('todo', JSON.stringify($scope.saved));
};
});
When retrieving the data from local storage check for existence then JSON.parse(localStorage.getItem('todo')) the get from local storage
In your case:
//you will need to parse the string to store it as an object
$scope.saved = JSON.parse(localStorage.getItem('todo'));
You can use the following factory:
yourApp.factory('$localStorage', ['$window', function($window) {
return {
store: function(key, value) {
$window.localStorage[key] = value;
},
get: function(key, defaultValue) {
return $window.localStorage[key] || defaultValue;
},
storeObject: function(key, value) {
$window.localStorage[key] = JSON.stringify(value);
},
getObject: function(key,defaultValue) {
return JSON.parse($window.localStorage[key] || defaultValue);
}
}
}]);
To use the factory you should inject it in your controller and use it like the following:
//to store
$localStorage.storeObject("sometoken", data);
//to retrieve
$localStorage.getObject("sometoken", "");
i solved my issue:
.controller("Appctrl",function($scope){
$scope.saved = localStorage.getItem('id');
$scope.id = JSON.parse($scope.saved);
localStorage.setItem('id', JSON.stringify($scope.id));
$scope.addTodo = function() {
//$scope.text=$scope.todoText;
$scope.id = [];
$scope.id.push({text:$scope.idText});
$scope.idText = ''; //clear the input after adding
localStorage.setItem('id', JSON.stringify($scope.id));
};
});
Check your code in controller.
You are doing : $scope.todo.push(text); instead of $scope.todos.push(text); itseems

View results of a search in the same View AngularJS

First sorry for my bad english. I'm developing an app to be able to study and was putting everything on the controller, all queries and all. But then I decided to pass it to a service (vi which is the right to do so), only when I queries for my search service just stopped working.
In the template I list all registered categories and it has an input, which makes the search all registered establishments in the DB. I wish that when you do a search, the list simply update with a new, only listing the results of this search.
When I try to do a search, the following error appears:
Object {message: "sqlite3_bind_null failure: bind or column index out of range", code: 0}
And so are all related to this template code and the search:
Service.js
app.service('Market', function($cordovaSQLite, DBA) {
var self = this;
self.allCategories = function() {
return DBA.query("SELECT id, category_name FROM tblCategories")
.then(function(result){
return DBA.getAll(result);
});
}
self.searchAll = function(nameSearch) {
var parameters = [nameSearch];
return DBA.query("SELECT id, place_name FROM tblPlaces WHERE place_name LIKE '%(?)%'", parameters)
.then(function(result) {
return DBA.getAll(result);
});
}
return self;
})
Controller.js
app.controller('CategoriesCtrl', function($scope, Market) {
$scope.categories = [];
$scope.categories = null;
$scope.items = [];
$scope.items = null;
var nameSearch = '';
$scope.searchkey = '';
$scope.myClick = function (search) {
nameSearch = search;
console.log(nameSearch);
$scope.searchResult = function(nameSearch) {
Market.searchAll(nameSearch).then(function(items) {
$scope.items = items;
console.log(items);
});
}
$scope.searchResult();
};
$scope.listAllCategories = function() {
Market.allCategories().then(function(categories) {
$scope.categories = categories;
});
}
$scope.listAllCategories();
})
Categories.html
<div class="bar bar-header item-input-inset">
<label class="item-input-wrapper">
<i class="icon ion-ios-search placeholder-icon"></i>
<input type="text" placeholder="Search" name="key" autocorrect="off" ng-model="searchkey">
</label>
<button class="button" ng-click="myClick(searchkey)">Buscar</button>
</div>
<ion-list>
<ion-item ng-repeat="category in categories">{{category.category_name}}</ion-item>
</ion-list>

how to add an object to list an array in angularjs

I am trying to add an object to the existing list. here is my code.
In controller:
$scope.itemList = [];
$scope.itemList = function () {
return itemService.getItemList();
};
getItemList read from a jason file locally not from service. now I am trying to add new object to this list.
here is my view:
<div>
<img src="/icon1.png" ng-click="sendNewItem()">
<input type="text" ng-model="itemtosend.itemName"/>
<input type="text" ng-model="itemtosend.itemNo"/>
</div>
In controller:
$scope.sendNewItem = function(){
var newItem = new function(){
this.itemName = $scope.itemtosend.itemName,
this.itenNo = $scope.itemtosend.itemNo,
}
$scope.itemList = $scope.itemList.push(newItem)
}
but Iam getting push is not a function. how to add the new object to the existing itemList?
You have many problems in your code :
//You define itemList as an Array (so you can push() in it)
$scope.itemList = [];
//But you redefine it as a function (you cannot push() to a function, ofc..
$scope.itemList = function () {
return itemService.getItemList();
};
then :
$scope.sendNewItem = function(){
//you say newItem is a function, but I guess what you want is an object
var newItem = new function(){
this.itemName = $scope.itemtosend.itemName,
this.itenNo = $scope.itemtosend.itemNo,
}
//$scope.itemList.push(newItem) is enough, no need for list = list.push("b")
$scope.itemList = $scope.itemList.push(newItem)
}
What you should have is :
In controller:
$scope.itemList = [];
$scope.sendNewItem = function(){
var newItem = {
itemName : $scope.itemtosend.itemName,
itenNo : $scope.itemtosend.itemNo
};
$scope.itemList.push(newItem)
}
Please find bellow a code snippet :
var app = angular.module("App", []);
app.controller("Ctrl", function($scope) {
$scope.itemList = [];
$scope.sendNewItem = function() {
var newItem = {
name: $scope.itemtosend.itemName,
no: $scope.itemtosend.itemNo
};
$scope.itemList.push(newItem)
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="App" ng-controller="Ctrl">
<label>Name :</label><input type="text" ng-model="itemtosend.itemName" />
<label>No :</label><input type="text" ng-model="itemtosend.itemNo" />
<button ng-click="sendNewItem()">Add</button>
<h3>Item List :</h3>
<div ng-repeat="item in itemList">
name : {{item.name}}, num : {{item.no}}
</div>
</div>

Angular best practices for splitting components

So i have this simple listing of system users (attached screenshot), client can edit the users or create new user and a new panel is displayed accordingly.
What I'm doing is updating the different fields of the edit/create form depending on the user action. But since im coming from a Backbone background, the usual way I would do something like this is to create a new view, initialize it with a parameter indicating whether it's a create or edit mode, and then destroy this view when clicking on cancel/save changes/create user. But right now im just depending on angular event binding to update the same form elements, is this the proper way to do it in angular?
$scope.prepare_form = function (user_id) {
if (user_id) {
// edit mode
var user = filterFilter($scope.users, { id: user_id })[0];
$scope.fdata_create.name = user.name;
$scope.fdata_create.email = user.email;
$scope.fdata_create.role_name = user.role_name;
$scope.fdata_create.id = user.id;
} else {
// create mode
$scope.fdata_create.name = '';
$scope.fdata_create.email = '';
$scope.fdata_create.role_name = '';
$scope.fdata_create.id = '';
}
$scope.form_create_open = true;
}
You should think based on Models rather than forms. You should create Teammate model with its sync methods, update, create, replace, etc. It is cleaner, here is example extract from this tutorial
Book html form.
<div ng-controller="BookController">
<div ng-style="{ backgroundImage: 'url(' + book.getImageUrl(100, 100) + ')' }"></div>
Id: <span ng-bind="book.id"></span>
<br/>
Name:<input type="text" ng-model="book.name" />
<br/>
Author: <input type="text" ng-model="book.author" />
<br/>
Is Available: <span ng-bind="book.isAvailable() ? 'Yes' : 'No' "></span>
<br/>
<button ng-click="book.delete()">Delete</button>
<br/>
<button ng-click="book.update()">Update</button>
</div>
Book Model define as factory.
app.factory('Book', ['$http', function($http) {
function Book(bookData) {
if (bookData) {
this.setData(bookData):
}
// Some other initializations related to book
};
Book.prototype = {
setData: function(bookData) {
angular.extend(this, bookData);
},
load: function(id) {
var scope = this;
$http.get('ourserver/books/' + bookId).success(function(bookData) {
scope.setData(bookData);
});
},
delete: function() {
$http.delete('ourserver/books/' + bookId);
},
update: function() {
$http.put('ourserver/books/' + bookId, this);
},
getImageUrl: function(width, height) {
return 'our/image/service/' + this.book.id + '/' + width + '/' + height;
},
isAvailable: function() {
if (!this.book.stores || this.book.stores.length === 0) {
return false;
}
return this.book.stores.some(function(store) {
return store.quantity > 0;
});
}
};
return Book;
}]);
Book controller that uses Book Model
app.controller('BookController', ['$scope', 'Book', function($scope, Book) {
$scope.book = new Book();
$scope.book.load(1);
}]);
If you want to update book name for example, you dont need to manually assign the new name because the Book's name instance is binded to ng-model attribute. To update it just only need call your update function from Book Factory.
$scope.book = new Book();
if(book_id){
$scope.book.load(book_id);
$scope.submit_book = $scope.book.update // submit_book function need to be triggered after submit the form. Here it
}
else{
$scope.submit_book = $scope.book.create // submit_book function need to be triggered after submit the form. Here it will create the book
}
I would reuse the same form, but bind to different models:
app.controller('ctrl', function($scope){
$scope.addUser = function(){
$scope.add= true;
$scope.user = {};
};
$scope.editUser =function(user){
$scope.add=false;
$scope.user ={};
angular.copy($scope.user, user);
};
$scope.onOK = function(user){
...
angular.copy(user, $scope.user);
};
});
HTML:
<div ng-controller="ctrl">
<form>
<input type ="text" ng-model="user.name" />
<input type="text" ng-model="user.role" />
<button ng-click="onOK(user)"> ok </button>
</form>
</div>

AngularJS - ng-click does not remove previous click's modifications when clicked again

So I am trying to acomplish this example: http://jsfiddle.net/pkozlowski_opensource/WXJ3p/15/
However, for some reason, when I click on one div, and then on another, it does not remove the "active" class from the previous div so it highlights both , hence all my divs end up with the class active if I click all of them. I want to make it to where it will actually remove the class if I click anywhere else on the body and also if I click on any other div, like the fiddle example.
My jsFIddle
http://jsfiddle.net/GeorgiAngelov/jUj56/4/
<div ng-controller="MyCtrl">
<button class="addQuestionButton btn btn-primary" ng-click="AddRootQuestion(questions)">Add node</button>
<div ng-repeat="question in questions" ng-include="question"> </div>
<script type="text/ng-template" id="question">
<!-- Single question starts here -->
<div ng-controller="QuestionController" ng-class="{active : isSelected(question)}">
<button class="btn btn-primary" ng-click="AddSubQuestion(question)">Add node</button>
<button class="btn btn-primary" ng-click = "editQuestion(question)">Edit Question</button>
</div>
<div ng-repeat="question in question.nodes" ng-include="question">
</div>
</script>
</div>
Since each single question has its own QuestionController, and QuestionControlleris where $scope.selected is being set, they don't interact with each other. That is to say, when you click edit, it sets selected for that individual controller.
The easy way to fix it would be to set a property on a parent scope (the containing controller) when clicking edit:
function MyCtrl($scope) {
$scope.questions = [];
$scope.AddRootQuestion = function(questions) {
questions.push({name: 'Question', nodes: []});
};
// added this method --v
$scope.setSelected = function(q) {
$scope.selected = q;
};
}
function QuestionController($scope) {
$scope.choices = [];
$scope.choice = {text: ''};
$scope.AddSubQuestion = function(question, $element) {
var newName = 'Name of question goes here';
question.nodes.push({name: newName, id: 'it goes in here', nodes: []});
};
// modified this method --v
$scope.editQuestion = function(question){
$scope.setSelected(question);
};
$scope.isSelected = function(question) {
return $scope.selected === question;
};
}
But this makes QuestionController dependent upon a parent controller. A much better design would be to move all the data and data manipulation methods into a service:
var myApp = angular.module('myApp',[]);
myApp.factory('Question', function() {
return {
questions: [],
addRootQuestion: function() {
this.questions.push({name: 'Question', nodes: []});
},
addSubQuestion: function(question, data) {
question.nodes.push(data);
},
setSelectedQuestion: function(question) {
this.selectedQuestion = question;
},
isSelectedQuestion: function(question) {
return this.selectedQuestion == question;
}
};
});
You can then inject the service into your controllers:
function MyCtrl($scope, Question) {
$scope.questions = Question.questions;
$scope.AddRootQuestion = function() {
Question.addRootQuestion();
};
}
function QuestionController($scope, Question) {
$scope.choices = [];
$scope.choice = {text: ''};
$scope.AddSubQuestion = function(question, $element) {
var newName = 'Name of question goes here';
Question.addSubQuestion(question, {
name: newName, id: 'it goes in here', nodes: []
});
};
$scope.editQuestion = function(question){
Question.setSelectedQuestion(question);
};
$scope.isSelected = function(question) {
return Question.isSelectedQuestion(question);
};
}
Example: http://jsfiddle.net/BinaryMuse/pZkBv/
If you wanted, you could build up a richer data model using JavaScript OOP principles; for example, you could have Question instances with methods for manipulating the questions, which themselves live inside an instance of QuestionContainer (or Survey or Test or whatever).

Resources