I can't seem to get my Wordpress JSON to work. I'm brand new to the AngularJS and Ionic worlds, so I've been reading and watching tutorials.
This is the relevant part of my app.js file:
(function() {
var app = angular.module('mybodyapp', ['ionic', 'angularMoment','LocalStorageModule']);
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider.state('index', {
url : '/',
templateUrl : 'index.html',
controller : 'MainController'
});
$stateProvider.state('list', {
url: '/list',
templateUrl: 'templates/list.html'
});
$stateProvider.state('edit', {
url: '/edit/:noteId',
templateUrl: 'templates/edit.html',
controller: 'EditCtrl'
});
$stateProvider.state('add', {
url: '/add',
templateUrl: 'templates/edit.html',
controller: 'AddCtrl'
});
$stateProvider.state('notes', {
url: '/notes',
templateUrl: 'templates/notes.html'
});
$stateProvider.state('posts', {
url: '/posts',
templateUrl: 'templates/posts.html',
controller: 'PostsCtrl'
});
$urlRouterProvider.otherwise("/");
});
// ...
I am able to grab data from Reddit through a controller, but not data from Wordpress. I found a good demo template but cannot figure out how to 'rewrite' the beginning of the JS controller. I removed the top of the original angular.module('starter.controllers', []) and put angular.module('mybodyapp') followed by:
.controller('AppCtrl', function($scope, $timeout, $rootScope) {
$rootScope.url = 'http://scottbolinger.com/wp-json/wp/v2/';
})
.controller('PostsCtrl', function( $scope, $http, DataLoader, $timeout, $ionicSlideBoxDelegate, $rootScope ) {
console.log('PostsCtrl');
$scope.loadPosts = function() {
DataLoader.get( $rootScope.url + 'posts' ).then(function(response) {
$scope.posts = response.data;
console.log( response.data );
}, function(response) {
console.log('error', response);
});
}
// Load posts on page load
$scope.loadPosts();
paged = 2;
$scope.moreItems = true;
// Load more (infinite scroll)
$scope.loadMore = function() {
if( !$scope.moreItems ) {
return;
}
var pg = paged++;
$timeout(function() {
DataLoader.get( $rootScope.url + 'posts' + '?page=' + pg ).then(function(response) {
angular.forEach( response.data, function( value, key ) {
$scope.posts.push(value);
});
if( response.data.length <= 0 ) {
$scope.moreItems = false;
}
}, function(response) {
$scope.moreItems = false;
console.log('error');
});
$scope.$broadcast('scroll.infiniteScrollComplete');
$scope.$broadcast('scroll.resize');
}, 1000);
}
$scope.moreDataExists = function() {
return $scope.moreItems;
}
// Pull to refresh
$scope.doRefresh = function() {
console.log('Refreshing!');
$timeout( function() {
$scope.loadPosts();
//Stop the ion-refresher from spinning
$scope.$broadcast('scroll.refreshComplete');
}, 1000);
};
})
.controller('PostCtrl', function($scope, $stateParams, DataLoader, $ionicLoading, $rootScope, $sce ) {
$ionicLoading.show({
noBackdrop: true
});
var singlePostApi = $rootScope.url + 'posts/' + $stateParams.postId;
DataLoader.get( singlePostApi ).then(function(response) {
$scope.post = response.data;
// Don't strip post html
$scope.content = $sce.trustAsHtml(response.data.content.rendered);
$ionicLoading.hide();
}, function(response) {
console.log('error', response);
});
});
The name in your ng-app directive must match your module name. The name in your ng-controller directive must match your controller name.
For more information on the ng-app directive see the AngularJS ng-app API Reference.
For the ng-controller directive, AngularJS ng-controller API Reference
UPDATE
The demo you grabbed has three controllers. You need to make them methods of angular.module
angular.module('mybodyapp').controller('AppCtrl',...
angular.module('mybodyapp').controller('PostsCtrl', function( $sc
angular.module("mybodyapp").controller('PostCtrl', function($scope
Related
Here is my controller code:
.controller('TransitCtrl', function ($ionicPlatform, $scope, $state, $q, $ionicSideMenuDelegate, $timeout, $http, design, config) {
$ionicSideMenuDelegate.canDragContent(false);
var vm = this;
vm.userImg = design.user_img;
vm.isGetStarted = false;
vm.getPV = true;
vm.getPL = false;
vm.showWelcome = false;
var counter = 1;
$ionicPlatform.ready(function(){
$timeout( function(){
var userDataStageFirst = {
url: config.baseURL + 'userDataStageFirst',
dataServer: {
serverTaskRequest: counter
}
}
var url = userDataStageFirst.url;
var dataServer = userDataStageFirst.dataServer;
$http.post(url, dataServer).success(function (data, status, headers, config) {
alert(data)
})
.error(function () {
alert("error");
});
}, 1000 );
});
})
And here is this app.js
.state('app.transit', {
url: '/transit',
views: {
'menuContent': {
templateUrl: 'templates/transit.html',
controller: 'TransitCtrl'
}
}
})
and My html page
<ion-view hide-nav-bar="true" ng-controller="TransitCtrl as vm">
<ion-content>
hello world
</ion-content>
</ion-view>
When I use $scope in place of vm its working perfectly good, but when I use vm, it sends 2 $http request to the server. Not being able to understand this concept here.
Try remove ng-controller="TransitCtrl as vm" from template.
and change to this
state('app.transit', {
url: '/transit',
views: {
'menuContent': {
templateUrl: 'templates/transit.html',
controller: 'TransitCtrl as vm'
}
}
})
Right now i am making an AngularJS+UI router install application. But i have a problem, the problem is, that i want to disable access to the views, associated with the install application. I want to do it in resolve in the state config.
But the problem is i need to get the data from a RESTful API, whether the application is installed or not. I tried making the function, but it loaded the state before the $http.get request was finished.
Here was my code for the resolve function:
(function() {
var app = angular.module('states', []);
app.run(['$rootScope', '$http', function($rootScope, $http) {
$rootScope.$on('$stateChangeStart', function() {
$http.get('/api/v1/getSetupStatus').success(function(res) {
$rootScope.setupdb = res.db_setup;
$rootScope.setupuser = res.user_setup;
});
});
}]);
app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/404");
$stateProvider.state('db-install', {
url: "/install/db",
templateUrl: 'admin/js/partials/db-install.html',
controller: 'DBController',
resolve: {
data: function($q, $state, $timeout, $rootScope) {
var setupStatus = $rootScope.setupdb;
var deferred = $q.defer();
$timeout(function() {
if (setupStatus === true) {
$state.go('setup-done');
deferred.reject();
} else {
deferred.resolve();
}
});
return deferred.promise;
}
}
})
.state('user-registration', {
url: "/install/user-registration",
templateUrl: "admin/js/partials/user-registration.html",
controller: "RegisterController"
})
.state('setup-done', {
url: "/install/setup-done",
templateUrl: "admin/js/partials/setup-done.html"
})
.state('404', {
url: "/404",
templateUrl: "admin/js/partials/404.html"
});
}]);
})();
EDIT:
Here is what my ajax call returns:
Try this way:
$stateProvider.state('db-install', {
url: "/install/db",
templateUrl: 'admin/js/partials/db-install.html',
controller: 'DBController',
resolve: {
setupStatus: function($q, $state, $http) {
return $http.get('/api/v1/getSetupStatus').then(function(res) {
if (res.db_setup === true) {
$state.go('setup-done');
return $q.reject();
}
return res;
});
}
}
})
Then inject setupStatus in controller:
.state('setup-done', {
url: "/install/setup-done",
templateUrl: "admin/js/partials/setup-done.html",
controller: ['$scope', 'setupStatus', function ($scope, setupStatus) {
$scope.setupdb = setupStatus.db_setup;
$scope.setupuser = setupStatus.user_setup;
}]
})
I want to make my views show only after the initial data is fetched and i am trying to accomplish this with a route resolve, but i can't get it to work. What am i doing wrong? Also my angular skills are a bit shabby so i aplogize in advance if my question is dumb.
Application.js :
var Application = angular.module('ReporterApplication', ['ngRoute']);
Application.config(['$routeProvider', '$interpolateProvider',
function($routeProvider, $interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
$routeProvider
.when('/packing/scan.html', {
templateUrl: 'packing/scan.html',
controller: 'PackingScanController',
resolve: {
initData : Application.PackingScanInit()
}
})
.when('/packing/stats.html', {
templateUrl: 'packing/stats.html',
controller: 'PackingStatisticsController'
})
etc
and here is my Scan.js file :
Application.PackingScanInit = function ($q,$timeout,$http) {
var serverData = "";
$http.get('/packing/scan.action')
.success(function(data){
serverData = data;
})
.error(function(data){
serverData = data;
});
return serverData;
}
Application.controller('PackingScanController', ['initData', '$scope', '$http', function(initData, $scope, $http) {
var packer = this;
// Message log model
packer.messageLog = [{
status : "",
message : null
}];
the files are included in this order.
service are singletons means there are initialized only one but time but if you simply return from service it will be called one time but if you return a function from service it will be called again and again .See Below Sample for working.
var app = angular.module('ajay.singhApp', [])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/view1', {
templateUrl: 'views/main.html',
controller: 'MainCtrl',
resolve: {
myVar: function (repoService) {
return repoService.getItems().then(function (response) {
return response.data;
});
}
}
})
.when('/view2', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.otherwise({
redirectTo: '/view1'
});
}]);
app.factory('repoService', function ($http) {
return {
getItems: function () {
return $http.get('TextFile.txt');
}
};
});
Try this:
Application.PackingScanInit = function ($q,$timeout,$http) {
return $http.get('/packing/scan.action')
.success(function(data){
return data;
})
.error(function(data){
return data;
});
}
Also you have to adjust your resolve to this:
resolve: {
initData : Application.PackingScanInit
}
Here is a specific working example:
(function() {
angular.module('app',['ngRoute']);
function TestCtrl($scope, initData) {
$scope.value = initData;
}
angular.module('app').config(function($routeProvider) {
$routeProvider.otherwise({
template: '`<p>Dude {{value}}</p>`',
controller: TestCtrl,
resolve: {
initData: function($http) {
return $http.get('test.json') //change to test-e.json to test error case
.then(function(resp) {
return resp.data.value; //success response
}, function() {
return 'Not Found'; // error response
});
}
}
});
});
})();
http://plnkr.co/edit/SPR3jLshcpafrALr4qZN?p=preview
I'm currently working on this AngularJS Tutorial: Learn to Build Modern Web Apps with Angular and Rails https://thinkster.io/angular-rails/ which I think is a great resource showing how to build Rails Web Apps with AngularJS.
So far, I've completed over two thirds of the tutorial successfully, but now I'm facing some issues with factory services. When I hit the post button to create new post, I get the following error:
Error message
angular.js?body=1:11608 TypeError: undefined is not a function
at Scope.$scope.addPost (http://0.0.0.0:3000/assets/home/mainCtrl.js?body=1:23:24)
It points to the code below in mainCtrl.js file:
posts.create({
title: $scope.title,
link: $scope.link,
});
the entire mainCtrl.js file:
angular.module('flapperNews')
.controller('MainCtrl', ['$scope', 'posts', function ($scope, posts) {
$scope.test = 'Hello world!';
$scope.posts = posts.posts;
$scope.posts.push({
title: $scope.title,
link: $scope.link,
upvotes: 0,
comments: [
{ author: 'Joe', body: 'Cool post!', upvotes: 0 },
{ author: 'Bob', body: 'Great idea but everything is wrong!', upvotes: 0 }
]
});
$scope.addPost = function () {
if (!$scope.title || $scope.title === '') { return; }
posts.create({
title: $scope.title,
link: $scope.link,
});
$scope.title = '';
$scope.link = '';
};
$scope.incrementUpvotes = function(post) {
posts.upvote(post);
};
}]);
In the above controller, if the addPost function is replaced with the one that was used in the tutorial before the factory create method was introduced, then it works fine.
Working code:
$scope.addPost = function(){
if(!$scope.title || $scope.title === '') { return; }
$scope.posts.push({
title: $scope.title,
link: $scope.link,
upvotes: 0
});
$scope.title = '';
$scope.link = '';
};
So somehow the factory's posts.create method is causing the issue (although posts.posts is accesible).
Below is post.js file which o.create method is causing the current issue
angular.module('flapperNews').factory('posts', ['$http',
function($http){
var o = {
posts: []
};
return o;
o.getAll = function() {
return $http.get('/posts.json').success(function(data){
angular.copy(data, o.posts);
});
};
o.create = function(post) {
console.log("o.create");
return $http.post('/posts.json', post).success(function(data){
o.posts.push(data);
});
};
o.upvote = function(post) {
return $http.put('/posts/' + post.id + '/upvote.json')
.success(function(data){
post.upvotes += 1;
});
};
resolve: {
postPromise: ['posts', function(posts){
return posts.getAll();
}]
}
}
]);
app.js file
angular.module('flapperNews', ['ui.router', 'templates'])
.config([
'$stateProvider',
'$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'home/_home.html',
controller: 'MainCtrl'
})
.state('posts', {
url: '/posts/{id}',
templateUrl: 'posts/_posts.html',
controller: 'PostsCtrl'
})
$urlRouterProvider.otherwise('home')
}]);
If someone knows what the underlying issue here, then please give advice. Many Thanks :-)
My rails version 4.0.2 and I'm using Linux Ubuntu 12.04
Some thoughts, if I can't get the factory methods working, then I might put those methods directly in controllers to resolve the issue, hopefully :-)
You returned the object too soon, the other functions didn't register (since they are function expressions, and not function declarations, they didn't get hoisted). Move your return o; to the end and it will work:
app.factory('posts', ['$http',
function($http){
var o = {
posts: []
};
o.getAll = function() {
return $http.get('/posts.json').success(function(data){
angular.copy(data, o.posts);
});
};
o.create = function(post) {
alert('In create!');
console.log("o.create");
return $http.post('/posts.json', post).success(function(data){
o.posts.push(data);
});
};
o.upvote = function(post) {
return $http.put('/posts/' + post.id + '/upvote.json')
.success(function(data){
post.upvotes += 1;
});
};
resolve: {
postPromise: ['posts', function(posts){
return posts.getAll();
}]
}
return o;
}
])
See this working Fiddle.
Your resolve statement should go in the home state in your app.js. As the tutorial says, "By using the resolve property in this way, we are ensuring that anytime our home state is entered, we will automatically query all posts from our backend before the state actually finishes loading."
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',
resolve: {
postPromise: ['posts', function(posts){
return posts.getAll();
}]
}
})
.state('posts', {
url: '/posts/{id}',
templateUrl: 'posts/_posts.html',
controller: 'PostsCtrl'
})
$urlRouterProvider.otherwise('home');
}]);
I've a problem with 2 resolves, one for each controller.
http://jsfiddle.net/pvivera/RhAHy/
var app = angular.module('testApp', [], function($routeProvider){
$routeProvider.when('/', {
template: 'Home {{model}}',
controller: 'HomeCtrl',
resolve: HomeCtrl.resolve
})
.when('/About', {
template: 'About {{model}}',
controller: 'AboutCtrl',
resolve: AboutCtrl.resolve
});
});
var HomeCtrl = app.controller('HomeCtrl', function($scope, HomeCtrlData){
$scope.model = HomeCtrlData;
});
HomeCtrl.resolve = {
HomeCtrlData: function($q, $timeout){
var deferred = $q.defer();
$timeout(function(){
return deferred.resolve('AboutCtrlResolver');
}, 2000);
return deferred.promise;
}
};
var AboutCtrl = app.controller('AboutCtrl', function($scope, AboutCtrlData){
$scope.model = AboutCtrlData;
});
AboutCtrl.resolve = {
AboutCtrlData: function($q, $timeout){
var deferred = $q.defer();
$timeout(function(){
return deferred.resolve('AboutCtrlResolver');
}, 2000);
return deferred.promise;
}
};
In the jsfiddler script, when the HomeCtrl want to resolve HomeCtrlData I receive this error Unknown provider: HomeCtrlDataProvider <- HomeCtrlData
If I change HomeCtrlData to AboutCtrlData in the HomeCtrl everything works, it seems that the only resolve that is assigned is AboutCtrl.resolve
Any idea?
The problem here is that app.controller() doesn't return the controller, it returns your application module. So you're assigning app.resolve twice, which is why it doesn't work for one of them.
I would suggest that you inline the resolve function like this instead:
var app = angular.module('testApp', [], function($routeProvider){
$routeProvider.when('/', {
template: 'Home {{model}}',
controller: 'HomeCtrl',
resolve: {
HomeCtrlData: function($q, $timeout) {
var deferred = $q.defer();
$timeout(function(){
return deferred.resolve('HomeCtrlData');
}, 2000);
return deferred.promise;
}
}
})
.when('/About', {
template: 'About {{model}}',
controller: 'AboutCtrl',
resolve: {
AboutCtrlData: function($q, $timeout) {
var deferred = $q.defer();
$timeout(function(){
return deferred.resolve('AboutCtrlData');
}, 2000);
return deferred.promise;
}
}
});
});