I am building a note taking application (something like a blog actually with different terms like post=note etc.) to practise my skills in AngularJS and Rails.
There is a sidebar on the left (controller Sidebar.js) which fetches all items form the Rails API and ng-repeats them to a list.
By clicking on one of them, the show.html renders inside ng-show on the right. The show view, has a link that lets you delete the item and then splices it from the sidebar on the left. After much blood, sweat and tears I believe I made it, except one detail: After deletion(=> destroy()) of the item, the wrong index gets deleted from the sidebar. I've tried to make it work with indexOf and then I console.logged the index - it always appears to be -1.
To share the same array of note objects I created a service that does that with a getter and a setter.
How can I delete the right item from the sidebar?
show.html
<div class="row">
<div class="col-lg-10">
<h3>{{ note.title }}</h3>
</div>
<div class="col-lg-2">
<button type="button" ng-click="destroy(note)" class="btn btn-default btn-xs pull-right">
<span class="glyphicon glyphicon-remove"></span></button>
</div>
</div>
<hr/>
<div class="note-description">
{{ note.description }}
<br>
</div>
Sidebar.js
var app = angular.module('notepadApp');
app.controller('SidebarController',
['$scope', '$http', '$routeParams', '$location', 'Note', 'ShareNoteScope',
function($scope, $http, $routeParams, $location, Note, ShareNoteScope) {
$scope.notes = Note.query(function (){
ShareNoteScope.setScope($scope.notes);
});
$scope.getClass = function (path) {
if ($location.path().substr(0, path.length) === path) {
return 'active';
} else {
return '';
}
}
}]
);
sidebar.html
<ul class="nav nav-stacked" ng-controller="SidebarController">
<li ng-repeat="note in notes.notes | orderBy: '-created_at'" class="note-li">
<a href="/notes/{{note.id}}" ng-class="getClass('/notes/{{note.id}}')"
class="" >
{{ note.title }}
</a>
<div ng-repeat="tag in note.tags">
<div class="label">{{ tag }}</div>
</div>
</li>
</ul>
NoteCtrl.js
'use strict';
var app = angular.module('notepadApp');
app.controller('NoteController',
['$scope', '$http', '$routeParams', '$location',
function($scope, $http, $routeParams, $location) {
}]
);
app.controller('NoteShowController',
['$scope', '$http', '$routeParams', '$location', 'Note', 'ShareNoteScope',
function($scope, $http, $routeParams, $location, Note, ShareNoteScope) {
if ($routeParams.id) {
Note.get({id: $routeParams.id}, function(note){
$scope.note = note.note;
});
}
else {
$scope.note = ShareNoteScope.getScope().notes[0].id;
}
//Destroy method for deleting a note
$scope.destroy = function(note) {
Note.remove({id: note.id}, function() {
var index = ShareNoteScope.getScope().notes.indexOf(note);
console.log(index);
ShareNoteScope.getScope().notes.splice(index, 1);
});
$location.path('/notes');
}
}]
);
app.controller('NoteCreateController',
['$scope', 'Note', '$routeParams', '$location','ShareNoteScope',
function($scope, Note, $routeParams, $location, ShareNoteScope) {
$scope.notes = ShareNoteScope.getScope().notes;
$scope.newNote = {};
$scope.createNote = function() {
Note.create($scope.note, function (newNote) {
$scope.notes.unshift(newNote.note);
$scope.newNote = '';
$scope.errors = '';
$location.path('/notes/'+newNote.note.id);
});
}
}]);
models.js
'use strict';
var app = angular.module('notepadApp');
app.factory('Note', ['$resource', function($resource) {
return $resource('/api/notes/:id', { id: "#id" }, {
get: {
method: 'GET'
},
query: {
method: 'GET',
isArray: false
},
create: {
method: 'POST'
}
});
}]);
app.factory('ShareNoteScope', function (Note) {
var $scope;
return {
setScope: function (scope) {
$scope = scope;
},
getScope: function () {
return $scope;
}
}
});
ShareNoteScope.getScope().notes contents
$$hashKey
"object:5"
created_at
"2015-11-29T09:07:18.614Z"
description
null
id
130
tags
[]
title
"5345"
updated_at
"2015-11-29T09:07:18.614Z"
user_id
1
We went to the bottom of this in the chat. And the problem probably had to do with note not referencing an object in ShareNoteScope.getScope().notes. So to get a correct reference, we used filter in this case:
JavaScript
$scope.destroy = function(note) {
Note.remove({id: note.id}, function() {
var res = ShareNoteScope.getScope().notes.filter(function(el){
return el.id == note.id;
});
note = res[0];
var index = ShareNoteScope.getScope().notes.indexOf(note);
console.log(index);
ShareNoteScope.getScope().notes.splice(index, 1);
});
$location.path('/notes');
}
Pass $index in destroy method along with note object
<div class="row">
<div class="col-lg-10">
<h3>{{ note.title }}</h3>
</div>
<div class="col-lg-2">
<button type="button" ng-click="destroy(note,$index)" class="btn btn-default btn-xs pull-right">
<span class="glyphicon glyphicon-remove"></span></button>
</div>
</div>
<hr/>
<div class="note-description">
{{ note.description }}
<br>
</div>
$scope.destroy = function(note, $index) {
Note.remove({id: note.id}, function() {
ShareNoteScope.getScope().notes.splice($index, 1);
});
$location.path('/notes');
}
Try this
Related
I have little problem with my angularJS directive, i want to display 2 photos in different way by using other html codes, but here comes a problem, that only one directive can works per page, the second one works only when i comment the previous one, there are no any errors in the browser console so i totally losing my mind trying to figure how to fix this problem.
ps displayed photos are taken form json file.
Angular:
(function(angular) {
'use strict';
angular.module('SinglePost', ['ngSanitize', 'ui.bootstrap'])
.controller('Controller', ['$scope', '$http', '$sce', '$location', function($scope, $http, $sce, $location) {
var weburl = document.URL;
var postId = weburl.substr(-2, 2)
$http.get(link + 'json=get_post&post_id=' + postId).then(function(response, date, content) {
$scope.content = response.data.post;
$scope.CategoryID = response.data.post.categories[0].id;
IDcategory = $scope.CategoryID
console.log(IDcategory)
$sce.trustAsHtml(content);
});
}])
.directive('myPost', function() {
return {
restrict: 'AEC',
scope: {
myPost: '='
},
templateUrl: '../common/directive/single-post.html'
};
});
})(window.angular);
(function(angular) {
'use strict';
angular.module('SinglePostsCategory', ['ngSanitize', 'ui.bootstrap'])
.controller('Controller', ['$scope', '$http', '$sce', '$location', function($scope, $http, $sce, $location) {
$http.get(link + 'json=get_category_posts&id=1').then(function(response, date, contents) {
$scope.myList = {
items: [
$scope.content = response.data.posts[0],
$scope.content = response.data.posts[0]
]
}
});
}])
.directive('myPost', function() {
return {
restrict: 'A',
scope: {
myPost: '='
},
templateUrl: '../common/directive/single-subpost_category.html'
};
});
})(window.angular);
HTML:
<div class="col-md-12">
<div ng-app="SinglePost">
<div ng-controller="Controller">
<div my-post="content">
<h1>CONTENT</h1></div>
</div>
</div>
<div class="row">
<div ng-app="SinglePostsCategory">
<div ng-controller="Controller">
<div ng-repeat="content in myList.items">
<div my-post="content">
<h1>CONTENT</h1></div>
</div>
</div>
</div>
</div>
</div>
any suggestion how to fix it? :)
function(angular) {
'use strict';
angular.module('SinglePost', ['ngSanitize', 'ui.bootstrap'])
.controller('SingleController', ['$scope', '$http', '$sce', '$location', function($scope, $http, $sce, $location) {
var weburl = document.URL;
var postId = weburl.substr(-2, 2)
$http.get(link + 'json=get_post&post_id=' + postId).then(function(response, date, content) {
$scope.content = response.data.post;
$scope.CategoryID = response.data.post.categories[0].id;
IDcategory = $scope.CategoryID
console.log(IDcategory)
$sce.trustAsHtml(content);
});
}])
.directive('mySinglePost', function() {
return {
restrict: 'AEC',
scope: {
myPost: '='
},
templateUrl: '../common/directive/single-post.html'
};
});})(window.angular);
angular.module('SinglePostsCategory', ['ngSanitize','ui.bootstrap'])
.controller('SinglePostsController', ['$scope', '$http', '$sce', '$location', function($scope, $http, $sce, $location) {
$http.get(link + 'json=get_category_posts&id=1').then(function(response, date, contents) {
$scope.myList = {
items: [
$scope.content = response.data.posts[0],
$scope.content = response.data.posts[0]
]
}
});
}])
.directive('mySinglePostsCategory', function() {
return {
restrict: 'AEC',
scope: {
myPost: '='
},
templateUrl:'../common/directive/singlesubpost_category.html'
};
});})(window.angular);
Rename your directive or your Controller name, Sometimes within the same page with two modules with the same controller name could cause the problem. I recommend to change both Controller names to be distinguishable.
For what I have seen I dont know why you need two module within one page . Can you combine it into one module and use two controllers?
HTML:
<div class="col-md-12">
<div ng-app="SinglePost">
<div ng-controller="SinglePostController">
<div my-single-post="content">
<h1>CONTENT</h1></div>
</div>
</div>
<div class="row">
<div ng-app="SinglePostsCategory">
<div ng-controller="SinglePostsController">
<div ng-repeat="content in myList.items">
<div my-single-posts-category="content">
<h1>CONTENT</h1></div>
</div>
</div>
</div>
</div>
You can not create same name directives even in the different module.
the module is used to divide the develop module,but it can't avoid polluting the namespace.if you want to use the module B in module A,you just need to inject module B like
angular.module('SinglePost', ['ngSanitize', 'ui.bootstrap','SinglePostsCategory'])
but make sure the directive and controller's name is different
I am using angularjs. I am trying to send parameters and object into the popup.
Click here:
Html code:
<script src="https://code.angularjs.org/1.4.9/angular.min.js"></script>
<script src="https://rawgit.com/dwmkerr/angular-modal-service/master/dst/angular-modal-service.js"></script>
<div class="container" ng-app="app" ng-controller="Controller">
<h3>Angular Modal Service</h3>
<a class="btn btn-default" href ng-click="show()">Show a Modal</a>
<p>{{message}}</p>
<!-- The actual modal template, just a bit o bootstrap -->
<script type="text/ng-template" id="modal.html">
<div class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" ng-click="close('Cancel')" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Yes ossssssssr No?</h4>
</div>
<div class="modal-body">
<p>It's your call...</p>
</div>
<div class="modal-footer">
<button type="button" ng-click="close('No')" class="btn btn-default" data-dismiss="modal">No</button>
<button type="button" ng-click="close('Yes')" class="btn btn-primary" data-dismiss="modal">Yes</button>
</div>
</div>
</div>
</div>
</script>
</div>
Js Code:
var app = angular.module('app', ['angularModalService']);
app.controller('Controller', function($scope, ModalService) {
$scope.url = 'google.com';
var obj= {};
obj.name = "test"
$scope.data = obj;
$scope.show = function() {
ModalService.showModal({
templateUrl: 'modal.html',
controller: "ModalController"
}).then(function(modal) {
modal.element.modal();
modal.close.then(function(result) {
$scope.message = "You said " + result;
});
});
};
});
app.controller('ModalController', function($scope, close) {
$scope.close = function(result) {
close(result, 500); // close, but give 500ms for bootstrap to animate
};
});
How to pass the scope url and data values into the popup.
I saw few example to pass using resolve.
Please check my example
try this:
ModalService.showModal({
templateUrl: 'modal.html',
controller: "ModalController",
resolve : {
data: function () {
return $scope.data
}
}
})
in model controller you can get data like
app.controller('ModalController', function($scope, close, data) {
$scope.close = function(result) {
close(result, 500); // close, but give 500ms for bootstrap to animate
};
});
Call broadcast with data to Your modal, and catch event:
var app = angular.module('app', ['angularModalService']);
app.controller('Controller', function($scope, $rootScope, ModalService) {
$scope.url = 'google.com';
var obj= {};
obj.name = "test"
$scope.data = obj;
$scope.show = function() {
ModalService.showModal({
templateUrl: 'modal.html',
controller: "ModalController"
}).then(function(modal) {
modal.element.modal();
modal.close.then(function(result) {
$rootScope.$broadcast('ModalController:set', {message: "You said " + result});
});
});
};
});
app.controller('ModalController', function($scope, close) {
$scope.close = function(result) {
close(result, 500); // close, but give 500ms for bootstrap to animate
};
$scope.$on('ModalController:set', function(event, data) {
for(var i in data) {
$scope[i] = data[i];
}
});
});
"showModal" has a property with name "resolve".It lets you to share (pass) parameters to the controller.For example:
ModalService.showModal({
templateUrl: 'modal.html',
controller: "ModalController",
resolve : {
data: function () { // ro you can pass a value in stead of function
return $scope.data
}
}
})
And in controller you can inject it like services or use it with scope like scope.data
I have a cart counter which is in header controller. and a add to cart button which is in image view controller. I want to set cart counter from the image view controller. SO every time add to cart is clicked it changes the cart value.
Header controller :
decorpotCtrls.controller('DecorpotCtrl', [ '$scope', '$routeParams', 'cart',
function($scope, $routeParams, cart) {
$scope.cartCounter = cart.getCartCounter();
} ]);
Image Controller : -
decorpotCtrls.controller('ImageViewController', [
'$scope',
'$routeParams',
'imageView',
'$auth',
'cart',
function($scope, $routeParams, imageView, $auth, cart) {
$scope.addToCart = function(groupid) {
console.log($auth.isAuthenticated());
return cart.addToCart(groupid);
};
} ]);
cart Html : -
<i class="glyphicon glyphicon-shopping-cart" aria-hidden="true"></i> Cart({{cartCounter}})
add to cart from image controller -
<div id="addToCart" class="btn btn-primary btn-lg buyNCartButton" ng-click="addToCart(groupid)">Add To Cart</div>
cart service -
services.service('cart', function($http){
var counter =0 ;
sessionStorage.setItem('cartCounter', counter);
//var
return {
checkout : function(){
},
addToCart : function(gruopid){
counter++;
return counter;
},
getCartCounter : function(){
return counter;
}
};
});
You could do one thing set method reference to $scope.cartCounter like
$scope.cartCounter = cart.getCartCounter;
Then on HTML you could call that method like cartCounter() that will get evaluated on each digest.
<i class="glyphicon glyphicon-shopping-cart" aria-hidden="true"></i>
Cart({{cartCounter()}})
Use $rootScope in controller. All $scopes are "childs" of $rootScope.
decorpotCtrls.controller('ImageViewController', [
'$rootScope',
'$scope',
'$routeParams',
'imageView',
'$auth',
'cart',
function($scope,$rootScope, $routeParams, imageView, $auth, cart) {
$scope.addToCart = function(groupid) {
$rootScope.counter++;
console.log($auth.isAuthenticated());
return cart.addToCart(groupid);
};
} ]);
I am having a problem loading a set of JSON data with NG CLICK. Without the clickButton function the data loads fine. Is my JSON data structured properly? Here is my fiddle. Click [here] (http://jsfiddle.net/al321/08rjqv4k/3/ "mouse over")
$scope.items = [
{
"Name":"Sam",
"Address":"Street",
"Phone":"111",
"status":"Available"
},
{
"Name":"Tom",
"Address":"Road",
"Phone":"222",
"status":"Busy"
},]
--js
var app = angular.module('myApp', []);
app.controller('myController',
['$scope', '$http', function($scope, $http) {
$scope.clickButton = function() {
$http.get('data.json').success(function(data) {
$scope.items = data.items;
});
}
}]);
Plunker
JS
var app = angular.module('myApp', []);
app.controller('myController', ['$scope', '$http', function($scope, $http) {
$scope.clickButton = function() {
$http.get('data.json').success(function(data) {
$scope.items = data;
});
}
}]);
Markup
<body ng-controller="myController">
<div ng-app="myApp">
<div ng-controller="myController">
<button ng-click='clickButton()'>Load Data</button>
<ul ng-repeat="item in items">
<li ng-repeat="(key, val) in item">{{key}}: {{val}}
</li>
</ul>
</div>
</div>
</body>
JSON
[
{
"Name":"Sam",
"Address":"Street",
"Phone":"111",
"status":"Available"
},
{
"Name":"Tom",
"Address":"Road",
"Phone":"222",
"status":"Busy"
}
]
Is this what you are trying to accomplish?
Just replace the contents of the clickButton() function with your ajax calls.
You forgot to put the () on ng-click="clickButton(). You need to actually call the function.
Plunker
To add the search functionality you mentioned in the comment, just add a filter to the first ng-repeat:
ng-repeat="item in items| filter: {Name: search}"
Plunker with search
I am new to angularjs.I am building a very simple web application.The code structure is given below.I have a simple view showing candidate list and seraching candidate from data base.
My Javascript controller:
appRoot.controller('CandidateController', function ($scope, $location, $resource) {
var searchcandidates={
Name:$("#txtname").val(),
Email:$("#txtemail").val()
};
var Listcandidates = $resource('/api/Candidate', {Name:$("#txtname").val(), Email:$("#txtemail").val()}, { update: { method: 'GET' } });
$scope.candidateslist = [];
Listcandidates.query(function (data) {
$scope.candidateslist.length = 0;
angular.forEach(data, function (CandidateData) {
$scope.candidateslist.push(CandidateData);
})
});
$scope.SearchCandidates = function () {
alert($("#txtname").val());
var list = $resource('/api/Candidate', { id: "2" } );
}
var init = function () {
}
init();
});
My Cshtml:
#{
Layout = null;
}
<div class="FormHeader"><span class="searCandidate"></span>Search Result</div>
<div class="blank"></div>
<div class="container-fluid">
<div class="row-fluid">
<div class="span2">
<!--Sidebar content-->
Search:
<label>Name</label>
<input type="text" id="txtname" name="name" />
<label>Email</label>
<input type="text" id="txtemail" name="email" />
<input type="button" value="Save" ng-click="SearchCandidates()" />
</div>
<div class="span10">
<!--Body content-->
<ul class="candidates">
<li ng-repeat="candidate in candidateslist"
class="thumbnail phone-listing">
#*<img ng-src="{{phone.imageUrl}}">
{{phone.name}}*#
<div class="item">
<span class="green leftMrg">{{candidate.name}}</span>
<span class="leftMrg">{{candidate.skill}}</span>
<span class="grey leftMrg">Resume ID: {{candidate.id}}</span>
<div class="blank"></div>
<div class="blank"></div>
</div>
<div class="item">
<span class="bold">{{candidate.exporganization}} </span>
<span>Education:{{candidate.eduname}}</span>
<span>{{candidate.totalexperience}}</span>
<span>Preferred Location: {{candidate.location}}</span>
</div>
<p></p>
</li>
</ul>
</div>
</div>
</div>
My app.js:
var appRoot = angular.module('main', ['ngRoute', 'ngGrid', 'ngResource', 'angularStart.directives', 'kendo.directives']); //Define the main module
appRoot
.config(['$routeProvider', function ($routeProvider) {
//Setup routes to load partial templates from server. TemplateUrl is the location for the server view (Razor .cshtml view)
$routeProvider
.when('/home', { templateUrl: '/home/main', controller: 'MainController' })
.when('/contact', { templateUrl: '/home/contact', controller: 'ContactController' })
.when('/about', { templateUrl: '/home/about', controller: 'AboutController' })
.when('/demo', { templateUrl: '/home/demo', controller: 'DemoController' })
.when('/candidate', { templateUrl: '/home/candidate', controller: 'CandidateController' })
.otherwise({ redirectTo: '/home' });
}])
.controller('RootController', ['$scope', '$route', '$routeParams', '$location', function ($scope, $route, $routeParams, $location) {
$scope.$on('$routeChangeSuccess', function (e, current, previous) {
$scope.activeViewPath = $location.path();
});
}]);
My CandidateController.cs
public class CandidateController : ApiController
{
CandidateSearchDAL objCandidateSearchDAL = new CandidateSearchDAL();
// GET api/<controller>
public IEnumerable<CandidateModel> Get()
{
List<CandidateModel> lstCandidates = objCandidateSearchDAL.GetSearchCandidates();
return lstCandidates;
}
// GET api/<controller>/5
public string Get(string id)
{
return "value";
}
// POST api/<controller>
public void Post(string Name, string Email)
{
}
// PUT api/<controller>/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/<controller>/5
public void Delete(int id)
{
}
}
The first time when the page loads it shows all the candidates perfectly calling the controller IEnumerable Get() method.But when I click save button it can not call the controller api.
I'm not see call:
$resource.$save()