AngularJS fetching single post by slug with $routeParams fails - angularjs

I am working on a small AngularJS blogging app (the framework version I use is 1.7.8).
I have managed to pull and display posts from an API I made myself.
I have a problem displaying a single post and I can't figure out its cause.
My app.js file:
angular.module('app', [
'ngRoute',
'app.controllers',
'ngSanitize'
]).config(['$routeProvider', function($routeProvider){
$routeProvider.when('/', {
templateUrl: 'templates/posts.html',
controller: 'PostsController'
}).when('/:slug', {
templateUrl: 'templates/singlepost.html',
controller: 'SinglePostController'
}).when('/page/:id', {
templateUrl: 'templates/page.html',
controller: 'PageController'
}).otherwise({
redirectTo: '/'
});
}]);
Of my two controllers, only the first works as desired:
// All posts
.controller('PostsController', ['$scope', '$http', function($scope, $http){
$http.get('api').then(function(response) {
//Categories
$scope.categories = response.data.categories;
// Posts
$scope.posts = response.data.posts;
// Pages
$scope.pages = response.data.pages;
});
}])
// Single post
.controller('SinglePostController', ['$scope', '$http', '$routeParams', function($scope, $http, $routeParams){
$http.get('api/{slug}').then(function(response) {
const slug = $routeParams.slug;
console.log(slug); //consoles the slug post
console.log(response.data.post); //consoles null
});
}])
Tthe SinglePostController displays post: null in the console. That puzzles me, especially since:
console.log(slug); shows any posts slug in the console;
replaceing {slug} with an actual slug
("the-future-of-oil", for instance), does display a single posts
data in the console.
Where is my mistake?

I have solved the problem by replacing $http.get('api/{slug}') with $http.get('api/' + slug).
Now, in the controller I have:
// Single post
.controller('SinglePostController', ['$scope', '$http', '$routeParams', function($scope, $http, $routeParams) {
const slug = $routeParams.slug;
$http.get('api/' + slug).then(function(response) {
//Send single post to the view
$scope.post = response.data.post;
});
}])
In the view I have:
<div class="content">
<h1>{{post.title}}</h1>
<div class="meta">Published on {{{post.created_at}} by {{post.first_name}} {{post.last_name}}</div>
<div class="post-content">{{post.content}}</div>
</div>
It works.

Try 'api/:slug'. Instead of {slug} in your http get

Related

angularjs view does not update after $http

edit: I'm using bootstrap, I think bootstrap tab is causing the
problem
View does not get updated after $scope variable update.
$scope.codeData
if i console the $scope.codeData, i can see the data, but does not render in view.
I have to click twice to get the view render correctly.
is there anything wrong with my code??
Thank you.
config
angular.module('SPAroutes', ['ngRoute', 'SPAcontrollers', 'SPAdirectives'])
.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider
.when('/admin', {
templateUrl: 'templates/views/admin.html',
controller: 'adminCtrl',
controllerAs: 'admin'
})
$locationProvider.html5Mode(true).hashPrefix('!');
}]);
Controller.js
angular.module('SPAcontrollers', ['ngRoute', 'SPAfactories', 'SPAdirectives']).controller('adminCtrl', ['$scope', '$http', '$location', '$window', '$SPAaccount', function ($scope, $http, $location, $window, $SPAaccount) {
this.dataRetrive = function(category){
$http.get('/ctrls/get/blockCode/header').then(function (res){
$scope.codeData = res.data;
console.log($scope.codeData);
$('#headerTab').tab('show');
}, function (err){
console.log(err);
})
};
}]);
admin.html
{{codeData}}
You are mixing up controllerAs with scope as phil mentioned in his comment on question. Instead of using scope here store values insidethis reference something like this.
angular.module('SPAcontrollers', ['ngRoute', 'SPAfactories', 'SPAdirectives']).controller('adminCtrl', ['$scope', '$http', '$location', '$window', '$SPAaccount', function ($scope, $http, $location, $window, $SPAaccount) {
var admin = this;
this.dataRetrive = function(category){
$http.get('/ctrls/get/blockCode/header').then(function (res){
admin.codeData = res.data;
console.log(admin.codeData);
$('#headerTab').tab('show');
}, function (err){
console.log(err);
})
};
}]);
and inside the view: admin.html
{{admin.codeData}}
here is working plunk for your refernce

AngularJS trouble with UI-Router and linking id from one controller to another

I originally had my app set up with ng-route and I'm now switching over to ui-route. I used to use "when('/json/galleries/:projectId')" to generate a gallery when a thumbnail was clicked. Now with "state" I can't seem how to pass my projectId to the gallery state to generate my gallery.
App Module
(function() {
'use strict';
var bhamDesignsApp = angular.module('bhamDesignsApp', ['ngAnimate', 'ngTouch', 'ngSanitize', 'ngMessages', 'ngAria', 'ui.router', 'mm.foundation', 'appControllers']);
bhamDesignsApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'partials/home.html',
controller: 'ProjectsController'
})
.state('gallery', {
url: '/gallery/:projectId',
templateUrl: 'partials/gallery.html',
controller: 'GalleryController'
});
});
})();
App Controller
(function() {
'use strict';
var appControllers = angular.module('appControllers', []);
appControllers.controller('ProjectsController', ['$scope', '$http',
function ($scope, $http) {
$http.get('app/json/projects.json').success(function(data){
$scope.projects = data;
});
$scope.orderProp = '-year';
}]);
appControllers.controller('GalleryController', ['$scope', '$stateParams', '$http',
function($scope, $stateParams, $http) {
$http.get('app/json/galleries/' + $stateParams.projectId + '.json').success(function(data) {
$scope.gallery = data;
});
}]);
})();
HTML
.row
.small-12.medium-3.columns(ng-repeat="project in projects | orderBy:orderProp | filter:categoryFilter")
.tmbnail-container
a(ui-sref="gallery")
img.tmbnail(ng-src="{{project.thumbnail}}")
.text
h5 {{project.title}}
h6 {{project.year}}
.small-12.medium-6.columns
a(ui-sref="gallery")
You don't pass any ID to the state.
Change it to
a(ui-sref="gallery({projectId: project.id})"
(assuming project has an id field that holds its ID)
Documentation that explains how to use ui-sref: http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.directive:ui-sref

Angular Js controller not firing with routes

I am having a problem with AngularJS, where suddenly one of my controllers refuse to execure.
I load it with route, and i know the route is loaded as the html page attached is requested and inserted into the ng-view div i have.
My routes
when('/products/', {
templateUrl: 'app/components/products/products.html',
controller: 'productsController'
}).
when('/products/:productId', {
templateUrl: 'app/components/products/product.html',
controller: 'productController'
}).
I did not see any problems in my controller so i tried replacing all content with just a simple console log, and yet it do still not execute.
angular.module('DietPlanApp').controller('productsController',
['$scope', function ($scope) {
console.log('Get my products!');
}]);
My other controller productController workes just fine.
angular.module('DietPlanApp').controller('productController',
['$scope', '$routeParams', '$location', 'productService', 'userService',
function ($scope, $routeParams, $location, productService, userService) {
productService.getProduct(userService.getUserToken(), $routeParams.productId, function (data) {
if(data.result) {
$scope.product = transferToPortionSize(data.product);
} else {
$location.path("/products/");
}
});
$scope.save = function () {
productService.save(userService.getUserToken(), transferToUnitSize($scope.product));
$location.path("/products/");
};
$scope.delete = function () {
productService.deleteProduct(userService.getUserToken(), $scope.product.id);
$location.path("/products/");
};
}]);
And i have verified that the js files for productsController is loaded correctly in the HTML head, in the same way productController is.
It looks like the result of a namespace collision. You are overwriting productsController in public/app/components/users/authController.js.
It was probably the result of a copy/paste that your forgot to rename. That seems like the most likely culprit.
See the screenshot here.

Angular Routing Params issue

I am using a module where I add in my first controller which is taking a service as a dependency. All the service is doing is bringing in some data.
Then I have a show function which I am adding on an anchor element in my view in order to be able to click on the the first name and then get the user's details.
My second controller takes the data from the first controller and then using $routeParams I am trying to show the data on the user view.
Is there something I am doing wrong here?
(function() {
var app = angular.module('test');
app.controller('testCtrl', ['$scope', 'testFactory', '$location', function($scope, testFactory, $location) {
testFactory.getContact().then(function(data) {
$scope.contacts = data.data;
});
$scope.show = function(firstname) {
$location.path('main/' + firstname);
};
}]);
app.controller('userCtrl', ['$scope', '$routeParams', function($scope, $routeParams) {
$scope.user = $scope.contacts[$routeParams.firstname];
}]);
}());
These are the routes
(function() {
var app = angular.module('test', ["ngRoute"]);
app.config(function($routeProvider, $locationProvider) {
$routeProvider
.when("/main", {
templateUrl: "main.html",
controller: "testCtrl"
})
.when("/main/:firstname", {
templateUrl: "contact.html",
controller: "userCtrl"
})
.otherwise({redirectTo:"/main"});
$locationProvider.html5Mode(true);
});
}());
This is the error I am getting in my console:
TypeError: Cannot read property 'any1' of undefined
where any1 is the is the first name.

Angular Ui-router can't access $stateParams inside my controller

I am very beginner in Angular.js, I am using the Ui-router framework for routing.
I can make it work upto where I have no parameters in the url. But now I am trying to build a detailed view of a product for which I need to pass the product id into the url.
I did it by reading the tutorials and followed all the methods. In the tutorial they used resolve to fetch the data and then load the controller but I just need to send in the parameters into the controllers directly and then fetch the data from there. My code looks like below. when I try to access the $stateParams inside the controller it is empty. I am not even sure about whether the controller is called or not.
The code looks like below.
(function(){
"use strict";
var app = angular.module("productManagement",
["common.services","ui.router"]);
app.config(["$stateProvider","$urlRouterProvider",function($stateProvider,$urlRouterProvider)
{
//default
$urlRouterProvider.otherwise("/");
$stateProvider
//home
.state("home",{
url:"/",
templateUrl:"app/welcome.html"
})
//products
.state("productList",{
url:"/products",
templateUrl:"app/products/productListView.html",
controller:"ProductController as vm"
})
//Edit product
.state('ProductEdit',{
url:"/products/edit/:productId",
templateUrl:"app/products/productEdit.html",
controller:"ProductEditController as vm"
})
//product details
.state('ProductDetails',{
url:"/products/:productId",
templateUrl:"app/products/productDetailView.html",
Controller:"ProductDetailController as vm"
})
}]
);
}());
this is how my app.js looks like. I am having trouble on the last state, ProdcutDetails.
here is my ProductDetailController.
(function(){
"use strict";
angular
.module("ProductManagement")
.controller("ProductDetailController",
["ProductResource",$stateParams,ProductDetailsController]);
function ProductDetailsController(ProductResource,$stateParams)
{
var productId = $stateParams.productId;
var ref = $this;
ProductResource.get({productId: productId},function(data)
{
console.log(data);
});
}
}());
NOTE : I found lot of people have the same issue here https://github.com/angular-ui/ui-router/issues/136, I can't understand the solutions posted their because I am in a very beginning stage. Any explanation would be very helpful.
I created working plunker here
There is state configuration
$urlRouterProvider.otherwise('/home');
// States
$stateProvider
//home
.state("home",{
url:"/",
templateUrl:"app/welcome.html"
})
//products
.state("productList",{
url:"/products",
templateUrl:"app/products/productListView.html",
controller:"ProductController as vm"
})
//Edit product
.state('ProductEdit',{
url:"/products/edit/:productId",
templateUrl:"app/products/productEdit.html",
controller:"ProductEditController as vm"
})
//product details
.state('ProductDetails',{
url:"/products/:productId",
templateUrl:"app/products/productDetailView.html",
controller:"ProductDetailController as vm"
})
There is a definition of above used features
.factory('ProductResource', function() {return {} ;})
.controller('ProductController', ['$scope', function($scope){
$scope.Title = "Hello from list";
}])
.controller('ProductEditController', ['$scope', function($scope){
$scope.Title = "Hello from edit";
}])
.run(['$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}])
.controller('ProductDetailController', ProductDetailsController)
function ProductDetailsController ($scope, ProductResource, $stateParams)
{
$scope.Title = "Hello from detail";
var productId = $stateParams.productId;
//var ref = $this;
console.log(productId);
//ProductResource.get({productId: productId},function(data) { });
return this;
}
ProductDetailsController.$inject = ['$scope', 'ProductResource', '$stateParams'];
Check it here
But do you know what is the real issue? Just one line in fact, was the trouble maker. Check the original state def:
.state('ProductDetails',{
...
Controller:"ProductDetailController as vm"
})
And in fact, the only important change was
.state('ProductDetails',{
...
controller:"ProductDetailController as vm"
})
I.e. controller instead of Controller (capital C at the begining)
The params in controller definition array should be strings
["ProductResource", "$stateParams"...
This should properly help IoC to inject the $stateParams
And even better:
// the info for IoC
// the style which you will use with TypeScript === angular 2.0
ProductDetailsController.$inject = ["ProductResource", "$stateParams"];
// this will just map controller to its name, parmas are defined above
.controller("ProductDetailController", ProductDetailsController);

Resources