Delete a id using Angular - angularjs

Users can search for a movie title in my inputfield and it will show them a list of movies. They can then hover over a title and a Add Movie button pops up. They can click it so it gets added to their frontpage. But now I'm trying to figure out how they can remove that movie from the database. But I can't find a clear example on how to do this.
This is how I show the movies,
%div{"ng-repeat" => "movie in movies"}
{{ movie.id }}
{{ movie.title }}
%a{"ng-click" => "deleteMovie($index)"}delete
I think I have to create a delete action in my controller called deleteMovie which works with a service to remove the id from the database.
This is how I see the service,
.factory('removeMovie', ['$http', function($http) {
return {
deleteMovie: function() {
return $http.delete('/movies.json/$id');
}
};
}])
The deleteMovie would be called in the controller. But I have the feeling I'm approaching this the wrong way.

Please follow the below code.
HTML View
%div{"ng-repeat" => "movie in movies"}
{{ movie.id }}
{{ movie.title }}
%a{"ng-click" => "deleteMovie(movie)"}delete
Controller
.controller('MainController', ['$scope','removeMovie',
function($scope, removeMovie) {
$scope.deleteMovie = function(movie){
removeMovie.deleteMovie(movie.id).then(function(sucessResponse){
//success callback
},function(errorResponse){
//Error callback
})
}
}
]);
Factory
.factory('removeMovie', ['$http', function($http) {
return {
deleteMovie: function(movieId) {
var _movieId = parseInt(movieId);
return $http.delete('/movies.json/'+_movieId);
}
};
}]);
if you are using the static json, then you do not need to make any rest request. You can simple splice the movie from movies array.if you are deleting movie from database then you need to make a rest request like this $http.delete('/movies/'+_movieId);

if the service only calls one http call, you might ass well write that already i your controller:
view:
%div{"ng-repeat" => "movie in movies"}
{{ movie.id }}
{{ movie.title }}
%a{"ng-click" => "deleteMovie(movie.id)"}delete
and inthe controller
.controller('myCtrl', ['$scope', '$http', function($scope, $http) {
$scope.deleteMovie = function(id) {
$http.delete('/movies.json/' + id);
}
}])

Pass in the whole movie object so that you can use it for the post but also to simply index it in the array for removal locally as well.
Adjust factory for id
.factory('removeMovie', ['$http', function($http) {
return {
deleteMovie: function(id) {
return $http.delete('/movies/' +id);
}
};
}]);
HTML
"ng-click" => "deleteMovie(movie)"}delete
Now make request from controller and remove from local array on completeion
$scope.deleteMovie = function(movie) {
removeMovie.deleteMovie(movie.id).then(function(resp){
// validate your response here before next step
// get index of movie in array
var idx = $scope.movies.indexOf(movie);
//remove from array
$scope.movies.splice( idx, 1);
});
}
Note that it seems strange to have a factory just for removeMovie.
Normally you would have all your CRUD operations in the same factory

Related

AngularJs Typeahead directive not working

I have a simple requirement wherein a list of users is displayed and display a search button on top to search for the users by name, something like a simplified LinkedIn Connections page.
My web app is developed on node.js but this one page has been developed on angular.js and for this search button, I have decided to use the typeahead directive. This is how the jade file looks like:
html(ng-app='geniuses')
head
title List All Geniuses!
link(href='//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css', rel='stylesheet')
script(src='http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js')
script(src="https://cdn.firebase.com/js/client/2.2.4/firebase.js")
script(src="https://cdn.firebase.com/libs/angularfire/1.1.2/angularfire.min.js")
script(src='js/listAllgeniuses.js')
body
div.container
div.page-header
h2 All Geniuses!
div(ng-app='geniuses',ng-controller='SearchAGenius')
input.form-control(placeholder='Genius',name='search-genius',ng-model="selected",typeahead="user for user in usersArr | filter:{'geniusid':$viewValue} | limitTo:8")
div(ng-app='geniuses',ng-controller='GetAllGeniuses')
ul
li(ng-repeat='user in users') {{ user.geniusid }}
The list of users are being fetched as an array from firebase. As you can see, the list of users is fetched using GetAllGeniuses controller and it works fine.. Here is the controller code:
(function (angular) {
var app = angular.module('geniuses', ["firebase"]);
app.controller('GetAllGeniuses', ["$scope", "$rootScope","$firebaseArray",
function($scope, $rootScope, $firebaseArray) {
var users = $firebaseArray(new Firebase("****));
$rootScope.usersArr = users;
$scope.users = users;
}
])
app.controller('SearchAGenius', ["$scope", "$rootScope",
function($scope, $rootScope) {
$scope.selected = '';
$scope.usersArr = $rootScope.usersArr;
}
])
}(angular));
This is how the data looks like(dummy):
[
{
geniusid: "new",
geniusname: ""
},
{
geniusid: "new",
geniusname: ""
},
{
geniusid: "news",
geniusname: ""
},
{
geniusid: "qazwsx",
geniusname: ""
}
]
I want to search using the geniusid (or name) in the search box... I have tried almost all ideas posted on the net but haven't been able to figure this out..
Any ideas would be appreciated.
Check out this Plunker I made using your demo.
A few things to note. You'll want to include Angular Bootstrap in your scripts and inject it into your module.
script(src='http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.13.0.min.js')
And
var app = angular.module('geniuses', ["firebase","ui.bootstrap"]);
Also, don't use $rootScope to pass data around. This is a prefect use for an angular service.
There's also no need to define ng-app everytime you're going to use angular.
Here's the rest of the plunker code that I modified to get this working.
html(ng-app='geniuses')
head
title List All Geniuses!
link(href='//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css', rel='stylesheet')
script(src='http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js')
script(src='http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.13.0.min.js')
script(src="https://cdn.firebase.com/js/client/2.2.4/firebase.js")
script(src="https://cdn.firebase.com/libs/angularfire/1.1.2/angularfire.min.js")
script(src="./app.js")
body
div.container
div.page-header
h2 All Geniuses!
div(ng-controller='SearchAGenius')
input.form-control(placeholder='Genius',name='search-genius',ng-model="selected",typeahead="user as user.geniusname for user in usersArr | filter:{'geniusid':$viewValue} | limitTo:8")
div(ng-controller='GetAllGeniuses')
ul
li(ng-repeat='user in users') {{ user.geniusid }}
And the JS
(function(angular) {
var app = angular.module('geniuses', ["firebase", "ui.bootstrap"]);
app.controller('GetAllGeniuses', ["$scope", 'GeniusFactory',
function($scope, GeniusFactory) {
$scope.users = GeniusFactory.users();
}
]);
app.controller('SearchAGenius', ["$scope", 'GeniusFactory',
function($scope, GeniusFactory) {
$scope.selected = '';
$scope.usersArr = GeniusFactory.users();
}
]);
app.factory('GeniusFactory', ["$firebaseArray", function($firebaseArray) {
//Create a users object
var _users;
return {
users: users
}
function users() {
//This will cache your users for as long as the application is running.
if (!_users) {
//_users = $firebaseArray(new Firebase("****"));
_users = [{
geniusid: "new",
geniusname: "Harry"
}, {
"geniusid": "new",
"geniusname": "Jean"
}, {
"geniusid": "news",
"geniusname": "Mike"
}, {
"geniusid": "qazwsx",
"geniusname": "Lynn"
}];
}
console.log(_users);
return _users;
}
}]);
})(angular);

$http.get method not working on ng-submit

I want $http.get method to work when a form is submitted.
Here is my code. The object $scope.questions is being set when the method is called but the data doesn't show up in the div. Moreover, when the $http.get method is outside the signIn() function it works just fine.
$scope.signIn = function(data) {
$location.path('/profile');
var url = "database/fetch_data.php?query=";
var query = "Select * from question where userId=2";
url += query;
$http.get(url).success(function(questionData) {
$scope.questions = questionData;
console.log($scope.questions);
});
};
<div>
User Profile
<br/>Question Posted
<br/>
<input ng-model="query.title" id="value" type="text" placeholder="Search by Title..." ">
<div>
<ul>
<li ng-repeat="question in questions | filter: query ">
{{question.title}}
</li>
</ul>
</div>
<br/>
</div>
You need to move your $location.path('/profile') inside your http request. Remember that a http request is async call. You should redirect after getting the data not before.
$scope.signIn = function(data) {
var url = "database/fetch_data.php?query=";
var query = "Select * from question where userId=2";
url += query;
$http.get(url).success(function(questionData) {
$scope.questions = questionData;
console.log($scope.questions);
$location.path('/profile');
});
};
If you're redirecting to another route with a completely separate scope you will lose any scope you're setting in the success handling.
From what I'm reading you're clicking a button to do an action. After that action you're redirecting to another page with a separate controller and trying to persist the data.
Unfortunately, Angular hasn't figured out a great way to do this. The easiest way to persist data through controllers and scope is to create a service that will store it in one controller and grab it in another controller.
For instance:
$scope.signIn = function(data) {
var url = "database/fetch_data.php?query=";
var query = "Select * from question where userId=2";
url += query;
$http.get(url).success(function(questionData) {
$location.path('/profile');
storageService.store("question", questiondata)
});
};
Your new factory to persist data through:
angular.module('moduleName').factory('storageService', [
function () {
return {
store: function (key, value) {
localStorage.setItem(key, JSON.stringify(value));
},
get: function(key) {
return JSON.parse(localStorage.getItem(key));
},
remove: function(key) {
localStorage.removeItem(key);
}
}
}
]);
Other controller to access data:
$scope.question = storageService.get("question");
// remove localstorage after you've grabbed it in the new controller
storageService.remove("question");
An alternative to doing the somewhat 'hacky' way of using localStorage to persist data through controllers is to use ui-router and have a resolve on the route you're redirecting to.
For instance:
$scope.signIn = function(data) {
$state.go('profile');
};
In your route file:
.state('profile', {
url: '/profile'
controller: profileControllerName,
templateUrl: 'profileHtmlTemplate.html',
resolve: {
'questions': [function() {
var url = "database/fetch_data.php?query=";
var query = "Select * from question where userId=2";
url += query;
$http.get(url).success(function(res) {
return res.data;
});
}]
}
}
In your profile controller:
Inject your 'questions' resolve into your controller and assign `$scope.question = questions;
This will make the HTTP call as soon as you click the route, return the data if successful, then render the page. It will NOT render the page if the resolve does not return success. This will ensure your data will be loaded before you load the page that depends on that data.
I would highly recommend using services to hold your HTTP calls for specific parts of your application. If you have a GET questions, POST question, PUT question. I would create a questionService and make all my HTTP methods there so you don't have to clutter your routes. You would only have to call:
.state('profile', {
url: '/profile'
controller: profileControllerName,
templateUrl: 'profileHtmlTemplate.html',
resolve: {
'questions': [function() {
return questionService.getQuestions(id).then(function(res) {
return res.data;
})
}]
}
}

AngularJS "then" sets up object but object is not accessible on Partial View

Folks,
I have following Button Click which calls AngularJS $scope.getCustomerById method
<div><button type="button" ng-click="getCustomerById(cust.CustomerNumber);">detail of
{{cust.CustomerNumber}} customer</button>
</div>
Now my Controller JS code for getCustomerById is as below
$scope.getCustomerById = function (id) {
CustomerService.getCustomer(id)
.then(function (data) {
$scope.customer = data.data; //which returns data correctly
$location.path('Customer/' + $scope.customer.CustomerNumber.trim());
}, function (error) {
alert(error);
});
};
and it goes to Designated View as well, but this View Does not render customer data. My CustomerView is very simple,
<div data-ng-controller="CustomerController">
{{ customer.CustomerNumber }}//this doesn't show anything, eventhough $scope.customer
//is set in controller as above
</div>
Any help will be really appreciated.

AngularJS ng-click linking to a model

I am building a small rss reader using Express(ie Jade) and Angular. I have a dropdown menu, where the menu items are populated by a list of items in a model.
Whatever the user chooses as an item, there is a rss url attached to it and it should trigger a factory.
This is the jade part:
div.btn-group
button.btn.btn-info(type='button') {{loadButtonText}}
button.btn.btn-info.dropdown-toggle(data-toggle='dropdown')
span.caret
span.sr-only Toggle Dropdown
ul.dropdown-menu(role='menu')
li(ng-repeat='rss in RSSList')
a(href='#', ng-click="feedSrc='{{rss.url}}';loadFeed($event);") {{rss.Title}}
input.form-control(type='text', autocomplete='off', placeholder="This is where your feed's url will appear" data-ng-model='feedSrc')
This is my angular controller:
var News = angular.module('myApp', []);
News.controller('FeedCtrl', ['$scope','FeedService', function($scope, Feed){
$scope.loadButtonText = 'Choose News Feed';
$scope.RSSList = [
{Title: "CNN", url: 'http://rss.cnn.com/rss/cnn_topstories.rss'},
{Title: "Reuters", url: 'http://feeds.reuters.com/news/usmarkets'}
];
$scope.loadFeed = function (e) {
Feed.parseFeed($scope.feedSrc).then(function (res) {
$scope.loadButtonText=angular.element(e.target).text();
$scope.feeds = res.data.responseData.feed.entries;
}); }}]);
News.factory('FeedService', ['$http', function($http){
return {parseFeed: function (url){
return $http.jsonp('//ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=50&callback=JSON_CALLBACK&q='+encodeURIComponent(url));}}
}]);
It seems feedSrc in ng-click doesn't capture rss.url and can not be passed as argument to the parseFeed function.
I tried to pass rss.url directly into loadFeed, like this ng-click="loadFeed({{rss.url}});" and even ng-click="loadFeed('{{rss.url}}');" I didn't work either.
Simply pass it this way :
ng-click="loadFeed(rss.url)"
No need to use the {{ }} in ng-click
Why not to use just:
Jade:
a(href='#', ng-click="loadFeed(rss.url,$event)") {{rss.Title}}
Controller:
$scope.loadFeed = function (url, e) {
Feed.parseFeed(url).then(function (res) {
$scope.loadButtonText=angular.element(e.target).text();
$scope.feeds = res.data.responseData.feed.entries;
}); }}]);

adding more than one sources of data to angular

this is what I have in my model
// The contents of individual model .js files will be concatenated into dist/models.js
(function() {
// Protects views where angular is not loaded from errors
if ( typeof angular == 'undefined' ) {
return;
};
var module = angular.module('myModel', ['restangular']);
module.factory('myRestangular', function(Restangular) {
return Restangular.withConfig(function(RestangularConfigurer) {
RestangularConfigurer.setBaseUrl('http://localhost/data');
RestangularConfigurer.setRequestSuffix('.json');
RestangularConfigurer.setRestangularFields({
id: "my_id"
});
});
});
})();
this is fine. but now I have another json that I need to grab data from. How could I change this model to look for that other json as well. I am very very new to angular and still learning how model data binding works!
*This is what I have tired *
my model
var module = angular.module('FloorModel', ['restangular']);
module.factory('FloorRestangular', function(Restangular) {
return Restangular.withConfig(function(RestangularConfigurer) {
RestangularConfigurer.setBaseUrl('http://localhost/data/floor');
RestangularConfigurer.setRequestSuffix('.json');
RestangularConfigurer.setRestangularFields({
id: "floor_id"
});
});
});
**my controller**
myApp.controller('FloorCtrl', function ($scope, $filter, FloorRestangular) {
// Fetch all objects from the local JSON (see app/models/mdpocket.js)
FloorRestangular.all('floor').getList().then( function(floors) {
// Then select the one based on the view's id query parameter
$scope.floor = $filter('filter')(floors, {floor_id: steroids.view.params['id']})[0];
});
// -- Native navigation
steroids.view.navigationBar.show("Floor: " + steroids.view.params.id );
});
*my view *
<div ng-app="myApp">
<div ng-controller="FloorCtrl">
<div class="topcoat-list__container">
<ul class="topcoat-list">
<li class="topcoat-list__item" hm-tap="open(floor.floor_id)" ng-repeat="floor in floors">
Floor Name: {{ floor.name }}
</li>
</ul>
</div>
</div>
</div>

Resources