I have built an test app very similar to the one from AngularJS' tutorial, with 1 major difference: It is initialized with Yeoman.
My factory code looks like this:
var deClashServices = angular.module('deClashServices', ['ngResource']);
deClashServices.factory('Session',
['$resource',
function ($resource) {
return $resource('views/sessions.json');
}]
);
Yes, angular-resource.js has been added to index.html. As well as my Controller, and Service js files.
Yes, deClashServices has been listed as a dependency on the ng-app, as seen here in my app.js:
var declashAngularApp = angular.module('declashAngularApp', [
'ngRoute',
'deClashServices',
'deClashControllers'
]);
declashAngularApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/sessions', {
templateUrl: 'views/sessions.html',
controller: 'SessionListCtrl'
})
.otherwise({
redirectTo: '/'
});
}]);
and here is my Controller:
var deClashControllers = angular.module('deClashControllers', []);
deClashControllers.controller('MainCtrl',
['$scope', 'Session',
function ($scope, Session) {
$scope.sessions = Session.query();
$scope.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
}]
);
in main.html, which is under MainCtrl, {{awesomeThings}} produces the array of 3 strings, as expected.
But {{sessions}} produces an empty array.
To pinpoint that it is .query() that's not loading it, I tried using a factory with a simple JSON file: {"sessions":"number1"}
deClashServices.factory('Session',
['$resource',
function ($resource) {
return $resource('views/simple.json');
}]
);
And my controller is like this:
deClashControllers.controller('MainCtrl',
['$scope', 'Session',
function ($scope, Session) {
$scope.sessions = {};
Session.get(function(response) {
$scope.sessions = response.sessions;
});
$scope.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
}]
);
This code works. Switching back to the JSON array and trying a callback with .query.$promise.then(callback-function) however, does not work.
I'm pretty lost and confused now, as the tutorial code from AngularJS with almost the exact same structure works.
I suspect that there's something wrong in the way I'm using .query(), but at the same time the same way is used by the Angular Tutorial and there isn't a problem there.
Just in case that it might be outside the few code snippets I've shown, here in the code for the entire project:
github
Angular's resource-service doesnt return promise. It returns an empty object so that when the request returns from server resource-service can populate that object with fetched data because it has a reference to that object.
So if you want to react to returning data you have to use a callback function or better yet
use $http-service, because it return promise.
Look at this plkr
I also recommend you take a look at Restangular
Related
recently I have tried to go through a ruby on rails + angular tutorial.
place i got stuck on : https://thinkster.io/tutorials/angular-rails/wiring-everything-up
so far : https://github.com/grfx1985/angular-rails-example
This tutorial is designed to go with rails-4. I have started building it on rails-5.
Up to this state I had no problems so far.
I got stuck on a bizarre problem. Trying to wire up the existing state of the app with the rails back-end. The method to get all the records - one of the first steps to combine the front with the back (last commit) is looping itself trying to receive the data from "posts.json". Eventually it crashes the browser (firefox, chrome - recent versions).
localhost:3000/posts.json dose render the json.
I went through the code comparing it with other people repositories to see if mixed something up, but still was not able to find what is wrong. At this point I am not sure what is the reason for this behavior.
APP.js :
angular.module('flapperNews', ['ui.router', 'templates'])
.config([
'$stateProvider',
'$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'home/_home.html',
controller: 'MainCtrl',
commented below app works:
-------------
resolve: {
postPromise: ['posts', function(posts){
return posts.getAll();
}]
}
-------------
})
.state('posts', {
url: '/posts/{id}',
templateUrl: 'posts/_posts.html',
controller: 'PostsCtrl'
})
$urlRouterProvider.otherwise('home');
}])
posts.js file :
angular.module('flapperNews')
.factory('posts', ['$http', function($http){
var o = {
posts: []
};
---- this is not working ----
o.getAll = function() {
return $http.get('/posts.json').success(function(data){
angular.copy(data, o.posts);
});
};
-----------------------------
o.create = function(post) {
return $http.post('/posts.json', post).success(function(data){
o.posts.push(data);
});
};
return o;
}])
As it turns out the version of angular provided via
//= require angular (1.6.2 at this time)
gets You the newest possible
so changing the setup and removing the line, and also including the initial script tag :
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
inside the application.html.erb file fixes the issue
Found this post because I'm also having the same issues, and managed to find a solution that allows you to continue to use 1.6.x. According to this page, the success() and error() methods have been deprecated, and replaced with then() and catch(). So, I changed the success() call to then() in my code, and it's working correctly for me.
posts.js:
angular.module('flapperNews')
.factory('posts', [
'$http',
function($http) {
var o = {
posts: []
};
o.getAll = function() {
return $http.get('/posts.json').then(function(data) {
angular.copy(data, o.posts)
})
};
return o;
}
]);
I'm trying to separate components into several files for a simple application but angular's dependency injector is giving me headaches and I don't really know what is expected.
Unknown provider: servicesProvider <- services <- maincontroller
Is the error I'm getting.
app.js
//Application definition with injected dependencies
var app = angular.module('leadcapacity', ['services', 'utils', 'customfilters', 'controllers']);
services.js
var services = angular.module('services', []);
services.service('xrmservice',
[
'$http', function($http) {
var oDataUrl = Xrm.Page.context.getClientUrl() + '/XRMServices/2011/OrganizationData.svc/';
var service = {};
service.query = function(entitySet, query) {
return $http.get(oDataUrl + entitySet + '?' + query);
};
return service;
}
]);
controllers.js
var ctrls = angular.module('controllers', ['utils', 'services']);
ctrls.controller('maincontroller',
function ($scope, services, utils) {
};
});
And the include order in index.html
<script src="service.js"></script>
<script src="controllers.js"></script>
<script src="app.js"></script>
Looks fine to me. I know this is perhaps not the best way to organize things, but getting a "Hello world" first would be nice.
Thanks.
Error message appearing in console clearly says that, services
dependency isn't exists in the module.
You have injected incorrect service name in maincontroller controller factory function, basically you were trying to to inject services(module name) instead of xrmservice(service name)
function ($scope, services, utils) {
should be
function ($scope, xrmservice, utils) {
Additional
Do follow Inline Array annotation of DI, as you were already used the same in your xrmservice service JS file, so that in future you don't need to go back and change that when you face javascript minification related issues.
Controller
ctrls.controller('maincontroller', [ '$scope', 'xrmservice', 'utils',
function ($scope, xrmservice, utils) {
//code goes here
//....
};
}]);
Although you have injected them into the module, you need to give them to the function so you can use the injected modules
ctrls.controller('maincontroller',
['$scope', 'services', 'utils', function ($scope, services, utils) {
};
}]);
I have a project where homeapp.js contains the angular.module dependencies:
var HomeApp = angular.module('HomeApp', [
'ngRoute',
'ngCookies',
'HomeControllers',
'metadataControllers',
'MyControllers',
'ScheduleControllers'
]);
HomeApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/schedules', {
templateUrl: 'pages/list_schedule.html',
controller: 'ScheduleControllers'
});
and in a ScheduleController.js, I have:
angular.module('ScheduleControllers', []).controller('PhoneListCrl', function($scope) {
$scope.phones = [
{'name': 'Nexus S',
'snippet': 'Fast just got faster with Nexus S.'},
{'name': 'Motorola XOOM with Wi-Fi',
'snippet': 'The Next, Next Generation tablet.'},
{'name': 'MOTOROLA XOOM',
'snippet': 'The Next, Next Generation tablet.'}
];
});
this is basically the code snippet from the angular tutorial.
In the index.html, I have:
<html lang="en-CA" ng-app="HomeApp">
...
<li id="id_schedule_list" class="header_list">List Schedule</li>
...
which then directs to this the schedules.html with only the follow codes:
<div>
<div ng-controller="PhoneListCrl">
<p>{{phones}}</p>
</div>
</div>
However when the html is opened from browser, it shows {{phones}} straight, without being able to show the full json object. The console says
https://docs.angularjs.org/error/ng/areq?p0=ScheduleControllers&p1=not%20a 1.#QNAN0unction%2C%20got%20undefined
Which doesn't really make sense to me, but I guess it is saying ScheduleControllers is undefined.
EDIT:
In angluar's tutorial, the app.js says:
var phonecatApp = angular.module('phonecatApp', [
'ngRoute',
'phonecatAnimations',
'phonecatControllers',
'phonecatFilters',
'phonecatServices'
]);
and then in controllers.js, it has:
var phonecatControllers = angular.module('phonecatControllers', []);
phonecatControllers.controller('PhoneListCtrl', ['$scope', 'Phone',
function($scope, Phone) {
$scope.phones = Phone.query();
$scope.orderProp = 'age';
}]);
Looks like I am almost doing exactly what the tutorial does, but why it doesn't work for me?
The problem is actually with the route. You are using the module's name for the controller instead of the actual controller name.
Where you have controller: 'ScheduleControllers', you instead need controller: 'PhoneListCtrl'. Additionally, the code you pasted has a typo in the controller definition. You need a t in PhoneListCtrl in
angular.module('ScheduleControllers', []).controller('PhoneListCtrl', function($scope) `
EDIT
In the following code, you are telling angular which controller to load when you access the /schedules route. Right now, it is pointing to 'ScheduleControllers', which is a module, not a controller. Change it to match the second block and you should be good to go.
HomeApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/schedules', {
templateUrl: 'pages/list_schedule.html',
controller: 'ScheduleControllers'
});
HomeApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/schedules', {
templateUrl: 'pages/list_schedule.html',
controller: 'PhoneListCtrl'
});
See https://docs.angularjs.org/tutorial/step_07 for reference.
You're attaching your controller to another Angular module:
// This line creates a new module named "ScheduleControllers"
// And attaches the "PhoneListCrl" to it.
angular.module('ScheduleControllers', []).controller('PhoneListCrl', function() { ... });
If you want it to be visible to your HomeApp then attach it to that module:
// You need to attach "PhoneListCrl" to your original module.
angular.module('HomeApp').controller('PhoneListCrl', function() { ... });
the controller: 'ScheduleControllers' is name of module and not controller, hence the issue
I have been all over the tutorial sites and couldn't get this working
I'm trying to make an angular app that works over the REST with my server(I downloaded this and managed to get it working but I started a new one from scratch to understand everything better). making the REST server was the easy part since I'm a php guy, but I'm not so familiar with angular part.
I made a simple directory with yeoman and put my REST server next to it in another folder, so I have :
root
------app with all angular code here
------engine which is a yii2 framework
in app/script/app.js I have:
'use strict'; // BTW what is this line doing?
var app = angular
.module('gardeshApp', [
'ngCookies',
'ngResource',
'ngSanitize',
'ngRoute'
])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/post/index' , {
templateUrl: 'views/post/index.html',
controller : 'PostList'
})
.otherwise({
redirectTo: '/'
});
});
I wanted make some kind of Model object to put received data in, so I created a Post model like :
app.factory('Post' , ['$resource'] , function($resource){
var Post = $resource('http://localhost/testApp/engine/web/post/:id' , {id : '#id'} , {update: {method: 'PUT'}});
angular.extend(Post.prototype , {
save: function (values) {
if (values) {
angular.extend(this, values);
}
if (this.id) {
return this.$update();
}
return this.$save();
}
});
});
and a controller to fetch the data:
app
.controller('PostList', ['$scope', '$http' , '$resource',
function($scope, $http) {
// $http.get('http://localhost/testApp/engine/web/post').success(function(data){
// console.log(data); // this works fine and gets the json ed data
// });
var posts = new Post();
console.log(posts.query());
}]);
I don't want to call $http.get myself, I want to make it dynamic but the Error says Post is not defined.
how can I make a proper Post Object to represent the model I'm fetching?
You may do something like this:
app.factory('Post' , ['$resource'] , function($resource){
var Post = $resource('http://localhost/testApp/engine/web/post/:id',
{
update: {method: 'PUT'}
}
);
return Post;
});
And,
app.controller('PostList', ['$scope', '$http' , 'Post',
function($scope, $http, Post) {
console.log(Post.query());
}]);
You need to return your built object in a factory in order to make it dependency-injectable later. Then in your controller, you need to declare that your want Post, and Angular will inject it for you.
I'm trying to create a simple blog website using AngularJS. I'm just starting out, so what I'm thinking my not be the best way to do this, so any alternative suggestions are welcome.
I have a controller.js file with two blog controllers. One to display a list of blog posts, and the other that displays the post content by including an HTML file.
controller.js
myAppControllers.controller('BlogListCtrl', ['$scope', '$http', function ($scope, $http) {
$http.get('articles/articles.json').success(function (articles) {
$scope.articles = articles;
});
}]);
myAppControllers.controller('BlogPostCtrl', ['$scope', '$routeParams', function ($scope, $routeParams) {
$scope.includeFile = 'articles/' + $routeParams.blogPostId + '.html';
}]);
articles.json
[
{
"id": "test-article-one",
"title": "Test Article one",
"author": "Gareth Lewis",
"datePosted": "2015-06-23",
"summary": "This is a test summary"
},
{
"id": "test-article-two",
"title": "Test article two",
"author": "Gareth Lewis",
"datePosted": "2015-06-23",
"summary": "This is a test for article two"
}
]
app.js
when('/blog', {
templateUrl: 'partials/blog-articles.html',
controller: 'BlogListCtrl'
}).
when('/blog/:blogPostId', {
templateUrl: 'partials/blog-post.html',
controller: 'BlogPostCtrl'
}).
blog-post.html
<ng-include src="'partials/header.html'"></ng-include>
<!-- Want to add title, author, datePosted information here... -->
<article class="content">
<ng-include src="includeFile"></ng-include>
</article>
This blog listings work fine. When I click into a blog post, it also serves up the content from the HTML file OK as well. However, I want to be able to reuse the title, author and datePosted properties from the selected article in the blog-post.html partial view. What's the best way to do this? Would I need to pass them to the Controller somehow to then pass to the view? I don't really want to pass these as routeParams. Or would I need to do a $http.get on articles.json and iterate through to find the selected article and then pass the property values back to the view?
Thanks for the help.
You said that suggestions are welcome, so here it goes.
1 - Transport all your Blog logic to a service;
2 - Provide the data on resolving routes. This is a better approach to handle errors during the load time, 404s, and so on. You can provide a listener to $routeChangeError and deal with it there;
3 - On the service declared below, you have the methods to call your data and a method to retrieve the list cached on the service:
// services.js
myAppServices
.service('BlogService', ['$http', '$q', function ($http, $q) {
var api = {},
currentData = {
list: [],
article: {}
};
api.getSaved = function () {
return currentData;
};
api.listArticles = function () {
var deferred = $q.defer(),
backup = angular.copy(currentData.list);
$http.get('articles/articles.json')
.then(function (response) {
currentData.list = response;
deferred.resolve(response);
}, function () {
currentData.list = backup;
deferred.reject(reason);
});
return deferred.promise;
};
api.getArticle = function (id) {
var deferred = $q.defer(),
backup = angular.copy(currentData.article),
path = 'articles/' + id + '.html';
$http.get(path, {
cache: true
})
.then(function (response) {
currentData.article = {
path: path,
response: response
};
deferred.resolve(currentData.article);
}, function (reason) {
currentData.article = backup;
deferred.reject(currentData.article);
});
return deferred.promise;
};
return api;
}]);
The BlogService.getSaved() will retrieve the stored data, made after each call.
I've made a method to call the ng-include path too, so you can verify if it exists, with cache === true, the browser will keep a copy of it, when calling it again on the view. A copy of the response of the blog article is made too, so you can access its path and the response whenever you need.
On the controllers below, they were adaptated to supply the current needs:
// controller.js
myAppControllers
.controller('BlogListCtrl', ['$scope', 'articles',
function ($scope, articles) {
$scope.articles = articles;
/* OTHER STUFF HERE */
}
])
.controller('BlogPostCtrl', ['$routeParams', '$scope', 'article' 'BlogService',
function ($routeParams, $scope, article, BlogService) {
// On `article` dependency, you have both the original response
// and the path formed. If you want to use any of it.
$scope.includeFile = article.path;
// To get the current stored data (if any):
$scope.articles = BlogService.getSaved().list;
// Traverse the array to get your current article:
$scope.article = $scope.articles.filter(function (item) {
return item.id === $routeParams.id;
});
/* OTHER STUFF HERE */
}
]);
And the route declarations were changed to load the data when resolving the routes.
// app.js
$routeProvider
.when('/blog', {
templateUrl: 'partials/blog-articles.html',
controller: 'BlogListCtrl',
resolve: {
articles: ['BlogService', '$routeParams', function (BlogService, $routeParams) {
return BlogService.listArticles();
}]
}
})
.when('/blog/:id', {
templateUrl: 'partials/blog-post.html',
controller: 'BlogPostCtrl',
resolve: {
article: ['BlogService', '$routeParams', function (BlogService, $routeParams) {
return BlogService.getArticle($routeParams.blogPostId);
}]
}
})
This is maybe a common question in angular. What you have to understand is that Scope is defined per controller... In order to share data across controller you still have the option to use $scope.$parent or $rootScope to link controllers but I would use those carefully.
It is better to use Angular Services which are based on singleton patterns therefore you can use them to share information between controllers and I think it will be a better approach.
I found that this has been previously discussed and here are some good examples:
AngularJS Service Passing Data Between Controllers
You can use a global scope to set this data, or you can use service to communicate between the controllers. There is a lot of ways to resolve this problem read a little bit more about services in the link bellow and see if you can find how to resolve your problem.
AngularJS: Service vs provider vs factory