I am really stuck with this REST API restangular config for my MEAN web application. So I have created the express server with node-restful API and can use POSTMAN to perform CRUD operations and my data is being saved to a MongoDB via Mongoose.
The client side application is a yeoman bootstrap using grunt and I can see hardcoded data in scope if I define it as per below in the controller, however when I attempt to GetList() with Restangular I am having the issue I can see posted previously with returning data from the API Restangular setbaseURL http://localhost:8080/horse.
I understand getList doesn't return data, the factory service is doing this, but I have it set like the examples online and cannot get it to return all records in the MongoDB to the angular view. Also tried ng-resource and I cannot understand why I can't add data from the API to scope.
Code below returns Horsename to "ngview" fine from HorseCtrl using <td>horse in horses</td> table
angular.module('HorseApp')
.controller('HorseCtrl', function ($scope) {
$scope.horses = [
{
horseName: 'MAYKBE DIVA'
}
];
});
below wont return data and my factory is set in app.js
'use strict';
angular.module('HorseApp', ['restangular']);
app.controller('HorseCtrl', function($scope, Restangular) {
$scope.horses = Restangular.all('horses').getList().$object;
});
app.js
'use strict';
angular.module('HorseApp', [
'ngRoute'
'restangular'
])
.config(function ($routeProvider, RestangularProvider) {
RestangularProvider.setBaseUrl('http://localhost:8081/horse');
$routeProvider
.when('/', {
templateUrl: '/views/index.html',
controller: 'HorsesCtrl'
});
})
.factory('HorseRestangular', function(Restangular) {
return Restangular.withConfig(function(RestangularConfigurer) {
RestangularConfigurer.setRestangularFields({
id: '_id'
});
});
})
.factory('Horse', function(HorseRestangular) {
return HorseRestangular.service('horse');
})
I have added the src to index.html as per below, please help :)
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-ui-select/dist/select.js"></script>
<script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="bower_components/bootstrap-sass-official/assets/javascripts/bootstrap.js"></script>
<script src="bower_components/angular-resource/angular-resource.js"></script>
<script src="bower_components/restanuglar/dist/restangular.js"></script>
From what I can see, you are globally setting the base url for Restangular to http://localhost:8081/horse, and in your HorseCtrl you are asking Restangular to access the horses endpoint and get the list. This will effectively access the data at http://localhost:8081/horse/horses. I am not sure if this is the intended path.
Your HorseRestangular and Horse factory are not being used. If you were to change the Restangular injection of the controller to Horse, it would access http://localhost:8081/horse/horse, and have the id available through the _id property. You don't necessarily need all of the services unless you will be communicating with more than one API through restangular. To simplify it, you can do this:
angular.module('HorseApp', ['restangular'])
.config(function ($routeProvider, RestangularProvider) {
RestangularProvider.setBaseUrl('http://localhost:8081');
$routeProvider
.when('/', {
templateUrl: '/views/index.html',
controller: 'HorsesCtrl'
});
});
})
.controller('HorseCtrl', function ($scope, Restangular) {
$scope.horses = Restangular.all('horses').getList().$object;
});
Related
I am trying to learn hot to invoke a RESTful service that I've implemented in JEE7. I am using the bootstrap template Angular-Seed and the file structure in the tutorial I am using looks a bit different. What I can't seam to figure out is how the $routeProvider and controller relate to each other.
The file structure I have look like this and is similar to the current Angular-Seed structure.
app/
bower_components/
components/
view1/
view1.html
view1.js
view1_test.js
view2/
view2.html
view2.js
view2_test.js
app.css
app.js
controller.js
service.js
index.html
index-async.html
Include the service and the controller in the index.html.
<script src="bower_components/angular-resource/angular-resource.js"></script>
<script src="services.js"></script>
<script src="controller.js"></script>
Added reference to the mainCtrl in app.js
'use strict';
// Declare app level module which depends on views, and components
angular.module('myApp', [
'ngRoute',
'myApp.view1',
'myApp.view2',
'myApp.version'
]).
config(['$routeProvider',
function ($routeProvider) {
$routeProvider.
when('/view1', {
templateUrl: 'view1/view1.html',
controller: 'mainCtrl'
})
}]);
In the services.js file I've declared the invocation of the RESTful service.
var tweetObsService = angular.module('tweetObsService', ['ngResource']);
tweetObsService.factory('tweetFactory', function($resource){
return $resource('http://localhost:8080/bongo-obs/rest/tweets/findAll', {}, {
query: {
method:'GET',
params: {},
isArray:true}
});
});
In the root file controller.js I've declared the mainCtrl.
angular.module('myApp')
.controller('mainCtrl', function($scope, tweetFactory) {
$scope.tweets = {};
tweetFactory.query().$promise.then(function(tweets) {
$scope.tweets = tweets;
});
});
The JSON that the service retrieves has the following structure.
[
{
"id": {
"timestamp": 1454579718,
"machineIdentifier": 12550416,
"processIdentifier": 6912,
"counter": 6510561,
"time": 1454579718000,
"date": 1454579718000,
"timeSecond": 1454579718
},
"userId": 0,
"status": null,
"user": {
"id": 291655833,
"name": "Anders Anderson",
"screenName": "Superuser",
"location": "Sweden",
...
Lats but not least, I tried to render result from the REST service in the view1/view1.html.
<table>
<tr ng-repeat="tweet in tweets">
<td>{{tweet.user.screenName}}</td>
</tr>
</table>
I've no alter the project thanks to submitted answer but I get an error related to the $injector
Error: [$injector:unpr] Unknown provider: tweetFactoryProvider <- tweetFactory <- mainCtrl
http://errors.angularjs.org/1.4.9/$injector/unpr?p0=tweetFactoryProvider%20%3C-%20tweetFactory%20%3C-%20mainCtrl
at http://localhost:8383/mobile-clear-obs/bower_components/angular/angular.js:68:12
at http://localhost:8383/mobile-clear-obs/bower_components/angular/angular.js:4346:19
at Object.getService [as get] (app/bower_components/angular/angular.js:4494:39)
at http://localhost:8383/mobile-clear-obs/bower_components/angular/angular.js:4351:45
at getService (app/bower_components/angular/angular.js:4494:39)
at invoke (app/bower_components/angular/angular.js:4526:13)
at Object.instantiate (app/bower_components/angular/angular.js:4543:27)
at http://localhost:8383/mobile-clear-obs/bower_components/angular/angular.js:9395:28
at link (app/bower_components/angular-route/angular-route.js:977:26)
at invokeLinkFn (app/bower_components/angular/angular.js:9039:9) (09:47:06:656 | error)
How do I correctly injection my mainCtrl, so I can use it in view1.html?
EDIT: Alter the question in response to the submitted.
2.
FINAL EDIT I finally got there with help from niklas. The last problem I stumbled upon is cross domain referencing, resulting in No 'Access-Control-Allow-Origin' header is present on the requested resource. If your backend is running on another server (still localhost), you have to allow cross domain calls to your back-end. Read this post how to solve this problem in JAX-RS 2.
The app.js
// Declare app level module which depends on views, and components
angular.module('myApp', [
'ngRoute',
'myApp.view1',
'myApp.view2',
'myApp.version',
'tweetObsService'
]).
config(['$routeProvider',
function ($routeProvider) {
$routeProvider.
when('/view1', {
templateUrl: 'view1/view1.html',
controller: 'mainCtrl'
})
}]);
The controllers.js
angular.module('myApp')
.controller('YourView1Controller', function($scope, tweetFactory) {
$scope.tweets = {};
tweetFactory.query().$promise.then(function(tweets) {
$scope.tweets = tweets;
}
}
For the view you can then access your desired data like
{{tweets.user.screenName}}and so on
To access the tweetFactory you have to declare the module tweetObsService. with the rest of the modules in myApp.
angular.module('myApp', [
'ngRoute',
'myApp.view1',
'myApp.view2',
'myApp.version',
'tweetObsService' //add this line
]). ...
Make sure your services.js is included in your index.html (some starter projects do it automatically...)
I'm following scotch.io's tutorial on building a RESTful API while trying to get familiar with the MEAN stack.
I've followed pretty much everything so far, and got my RESTful API sending out JSON as intended. Should I try to access it via browser address bar or try it out with Postman it works.
I'm having problems with the consumption of said JSON response.
According to the tutorial, the Angular app is divided in controllers and services. The service uses $http to call the RESTful endpoint. My doubt is where and how should I use that service to call for the data.
Is it in the controller? Is the service exposed in a way that I can add its response to $scope?
I'm new to Angular/client-side routing, so please be gentle:) My code is below.
(Blog) Controller:
angular.module('BlogCtrl', []).controller('BlogController', function($scope, $http) {
$scope.tagline = 'Blog page!';
// can and should I call the service here?
});
Service:
angular.module('BlogService', []).factory('Post', ['$http', function($http) {
return {
// call to get all posts
get : function() {
return $http.get('/api/blog');
}
}]);
Routes:
angular.module('appRoutes', []).config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider
// blog page that will use the BlogController
.when('/blog', {
templateUrl: 'views/blog.html',
controller: 'BlogController'
})
$locationProvider.html5Mode(true);
}]);
Angular App:
angular.module('myApp', ['ngRoute', 'appRoutes', 'MainCtrl', 'BlogCtrl', 'BlogService']);
Yes, you can make $http call in your BlogController.
However if you want to use your 'Post' factory, you should inject it to controller
angular.module('BlogCtrl', []).controller('BlogController', function($scope, Post) {...}
and make the request
Post.get().then(
function(response){console.log(response.data)},
function(errorResponse){/*...*/}
);
(I think you should also read about $resource (https://docs.angularjs.org/api/ngResource/service/$resource). Maybe it is something what you could use to replace your Post factory ;))
You want to inject the service into controller ( or anywhere else you would use it) and then make the function call using the injected service object
angular.module('BlogCtrl', [])
.controller('BlogController', function($scope, Post) {
$scope.tagline = 'Blog page!';
// Use service to get data
Post.get().then(responsePromise){
$scope.someVariable = responsePromise.data;
}).catch(function(err){
console.warn('Ooops error!')
});
});
I am trying to run an $http function when my AngularJS application first loads.
This $http function needs to finish before any of the controllers in my application could properly function. How would I go about doing this? This sounds like a promise, but it sounds like I would be creating a promise in each controller...
I currently have the function that I want to run first like this:
app.run(function() {
$http.get('link').success(function(data) {
// success function. The data that I get from this HTTP call will be saved to a service.
}).error(function(error) {
});
});
However, sometimes the controller will load before the http call finishes.
The problem
Angular is not dynamic, you cannot add controller dynamically neither factory, etc. Also you cannot defer controller bootstrap, angular loads everything together, and it's quite disadvantage (will be fixed in Angular 2)
The cure
But javascript itself has very important feature - closure, which works anywhere, anytime.
And angular has some internal services that can be injected outside of angular ecosystem, even into browser console. Those services injected as shown below. We technically could use anything else (jQuery.ajax, window.fetch, or even with XMLHttpRequest), but let's stick with total angular solution
var $http_injected = angular.injector(["ng"]).get("$http");
The act
First of all, we defer whole angular app bootstrap, inject http service. Then you make your needed request, receive data and then closure get's to work, we pass received data into some service, or we could also assign in to some angular.constant or angular.value but let's just make demo with angular.service, so when your service has data, bootstrap whole app, so that all controllers get initialized with your needed data
Basically that kind of tasks solved like this
<body>
<div ng-controller="Controller1">
<b>Controller1</b>
{{text}}
{{setting.data.name}}
</div>
<hr>
<div ng-controller="Controller2">
<b>Controller2</b>
{{text}}
{{setting.data.name}}
</div>
<script>
//define preloader
var $http_injected = angular.injector(["ng"]).get("$http");
$http_injected.get('http://jsonplaceholder.typicode.com/users/1').then(function(successResponse) {
//define app
angular.module('app', []);
//define test controllers
//note, usually we see 'controller1 loaded' text before 'settings applied', because controller initialized with this data, but in this demo, we will not see 'controller1 loaded' text, as we use closure to assign data, so it's instantly changed
angular.module('app').controller('Controller1', function($scope, AppSetting) {
$scope.text = 'controller1 loaded';
$scope.setting = AppSetting.setting;
$scope.$watch('setting', function(e1 ,e2){
$scope.text = 'settings applied'
});
});
angular.module('app').controller('Controller2', function($scope, AppSetting) {
$scope.text = 'controller2 loaded';
$scope.setting = AppSetting.setting;
$scope.$watch('setting', function(e1 ,e2){
$scope.text = 'settings applied'
});
});
//define test services, note we assign it here, it's possible
//because of javascript awesomeness (closure)
angular.module('app').service('AppSetting', function() {
this.setting = successResponse;
});
//bootstrap app, we cannot use ng-app, as it loads app instantly
//but we bootstrap it manually when you settings come
angular.bootstrap(document.body, ['app']);
});
</script>
</body>
Plunker demo
You can do this when you configure your routes
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/', {
controller: 'MainCtrl',
templateUrl: 'main.html',
resolve: {
data: ['$http',
function($http)
{
return $http.get('/api/data').then(
function success(response) { return response.data.rows[0]; },
function error(reason) { return false; }
);
}
]
}
});
}]);
Similar question:
AngularJS - routeProvider resolve calling a service method
AngularJS: $routeProvider when resolve $http returns response obj instead of my obj
Heres a plunkr I found using a service, which is what I would recommend.
http://plnkr.co/edit/XKGC1h?p=info
I am using Angular and I need to define routing in ng-route config but also in my services to be used by $http in services methods.
The problem is that the route strings change in my application according to language ... For example for an about us page I might have:
"en/about-us", "pt/quem-somos", "fr/ ..."
The application has a RouteProvider that returns route strings by key.
The idea would be to create a script on the fly for a service that injected in angular components would allow to get those routes strings.
<script type="text/javascript">
// Create $routes service using backend code ...
</script>
This would be used on app.config as follows:
app.config(['$routeProvider', function($routeProvider, $routes) {
$routeProvider.
when($routes.getByKey('about.home', {
templateUrl: 'about/home.html',
controller: 'AboutController'
})
}
But also in a service as follows:
application.service('CountryService', function ($http, $routes) {
return {
GetList: function () {
return $http.get($routes.getByKey('api.countries.list');
}
}
});
My problem is how to write the JS part of such a service and to plug it into angular components. Is it possible to create such a service?
I would not conflate view routes from the API endpoints - these are different creatures.
And you don't need to create a route per language - just use language as a parameter:
$routeProvider
.when("/:lang/about-us", {
template: "<h3>About Us</h3> in lang: {{language}}",
controller: function($scope, $routeParams, $location){
$scope.language = $routeParams.lang;
}
})
.when("/:lang/something-else", {
template: "<h3>Something Else</h3> in lang: {{language}}",
controller: function($scope, $routeParams){
$scope.language = $routeParams.lang;
}
})
plunker
I realise there are a few answers to this question on here, but I just can't seem to get them working with my set up. This is a Plunker of what I am trying achieve (not my own work): http://plnkr.co/edit/Ofq7Md8udEnIhAPF1NgL?p=preview
Currently, I have this for my index.html file:
<body ng-app="HomeCourtArenaApp">
<div class="container" ng-view></div>
<script src="components/angular/angular.js"></script>
<script src="components/require/require.js"></script>
<script src="components/angular/angular-resource.js"></script>
<script src="scripts/services/data.js"></script>
<script src="scripts/app.js"></script>
</body>
To register the components, I have defined them in the karma.conf.js file:
files = [
JASMINE,
JASMINE_ADAPTER,
'app/components/angular/angular.js',
'app/components/angular/angular-resource.js',
'app/components/angular-mocks/angular-mocks.js',
'app/scripts/*.js',
'app/scripts/**/*.js',
'test/mock/**/*.js',
'test/spec/**/*.js'
];
To then create the service, I use the same technique that seems to be documented online in most examples:
'use strict';
angular.module('jsonData', ['ngResource'])
.factory('jsonData', function($resource) {
return $resource('data/shoe3Dconfig.js');
});
Where an error seems to be triggered is when I try to define the service in my 'app' variable, where adding the service name stops the content loading ['jsonData']:
'use strict';
var app = angular.module('HomeCourtArenaApp', ['jsonData']);
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.otherwise({
redirectTo: '/'
});
});
I would share my views and controllers also, but before I can even use the JSON data in my template, there are an unearthly amount of errors to deal with:
Uncaught Error: Module name "path" has not been loaded yet for context: _. Use require([])
Uncaught Error: Mismatched anonymous define() module: function () {
return getStyleProperty;
}
Uncaught Error: No module: ngResource
There are some other errors also, but these seem to be mainly because the scripts further up the DOM are stopping them loading correctly. Any help would be great!
you could try this :
the app.js:
angular.module('HomeCourtArenaApp', ['HomeCourtArenaApp.services', 'HomeCourtArenaApp.controllers']).
config(['$routeProvider', ($routeProvider) {
$routeProvider.when('/', { templateUrl: 'views/main.html', controller: 'MainCtrl' });
$routeProvider.otherwise({ redirectTo: '/'});
}]);
angular.module('HomeCourtArenaApp.services', ['ngResource']).
factory('JsonData', function($resource){
return $resource('data/shoe3Dconfig.js');
});
angular.module('HomeCourtArenaApp.controllers', []).
controller('MainCtrl', ['$scope', 'JsonData', function($scope, JsonData) {
$scope.objs = JsonData.query();
console.log(objs);
}
}]);
and this is not necessary to load the datas in the html
<script src="scripts/services/data.js"></script>
This edited plunker http://plnkr.co/edit/33qW5VRnQVrHWFlp16kz?p=preview should get you further along the way.
You need to specify the module (jsonData) that you want in your app as a dependency. There is currently no name displayed since your data does not have a name property.
Your JSON service module definition named as 'jsonData'
angular.module('jsonData', ['ngResource'])
This module defines a service provider (factory) 'jsonService'
.factory('jsonService', function($resource) {
You list the 'jsonData' module as a dependency for your module so that you can access anything defined in there
var app = angular.module('plunker', ['jsonData']);
You then use Angular's Dependency Injection to request an instance of jsonService
app.controller('MainCtrl', function($scope, jsonService) {
Note that if you "production-ise" this and minify your JS, you will need to configure the DI code. I will leave that to you to find in the Angular docs.
Does this explain things a bit more?
And you can get the console in plunker by opening the developer tools in your browser.