$routeParams undefined when passing to new view & controller - javascript

Fairly new to AngularJS and WebAPI here, and figure the best way to learn is by doing. Apologies in advance if this question seems simple - I've spent a day flipping through StackOverflow and tried them all.
I currently have a separate Master & Detail view, both with their own controller. I am trying to pass the selected ID through to the Details controller so I can query my database using the ID, though am getting "undefined" on my $routeParams. I'm unsure if I am missing something simple, or whether I'm even approaching this correctly.
The controller doesn't seem to like it when I inject '$routeParams' either.
My app.js module:
var app = angular.module("ProjectDashboardModule", ["ngRoute"]);
app.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$routeProvider
.when("/", { templateUrl: "/Home/Index" })
.when("/Project", { templateUrl: '/Project/Index', controller: 'ProjectCrudController' })
.when("/Project/project/:id", {templateUrl:'/Project/project', controller: 'ProjectTaskController' });
$routeProvider.otherwise({redirectTo: '/home' });
$locationProvider.html5Mode(true);
}]);
my Factory.js:
app.factory('projectFactory', ['$http', function ($http) {
var urlBase = '/api/Projects/';
var projectFactory = {};
projectFactory.getProjects = function () {
return $http.get(urlBase);
};
projectFactory.getSingleProject = function (id) {
return $http.get(urlBase + '/' + id);
};
return projectFactory;
}]);
my ProjectTaskController.js:
app.controller('ProjectTaskController', ['$scope', "$routeParams", 'projectFactory', function ($scope, $routeParams, projectFactory) {
alert($routeParams.id)
$scope.project;
$scope.message;
getProjectById($routeParams.id);
function getProjectById(id) {
projectFactory.getSingleProject(id)
.success(function (data) {
$scope.project = data;
})
.error(function (error) {
$scope.message = 'error retrieving project ' + error.message;
});
}
}]);

I found that my problem was that all my angular script references were scattered. I moved all my custom script references (controller, factory, module) to index.cshtml and fixed the issue.

Related

Angular JS Routing Issue with MVC Area

I am new to Angular JS. I have a MVC Area called "Setup". Under this area there is a Controller called ModuleMstController.
The above controller has an Action method GridData.
From my Angular controller i make a post with a url /Setup/ModuleMst/GridData
but firebug shows the request url as
http://localhost/ModuleMst/GridData
and my action method is not hit.
I then tried to configure routing as
var ap = angular.module('myApp', ['trNgGrid', 'ngRoute']);
//controller 1
ap.controller("MainCtrl", function ($scope, $http) {
$scope.model = {};
......
....
$scope.isAjaxInProgress = true;
$scope.errorMessage = undefined;
$http.post("/ModuleMst/GridData", $scope.requestedItemsGridOptions)
.then(function (data) {
$scope.model.itemList = data.items;
$scope.model.totalCount = data.TotalCount;
}
,function () {
$scope.errorMessage = "An Error has occured while loading data!";
});
})
.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$routeProvider.when('/ModuleMst', {
templateUrl: '/Setup/ModuleMst/GridData'
//controller: 'ModuleMst',
});
$routeProvider.otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(false).hashPrefix('!');
}]);
I have not touched the routing configuration in the server side. It works with jquery ajax but not with angular $http.post().
How do i make this work ?
Thanks for the help.
Pass the MVC area in the http post:
$http.post("/Setup/ModuleMst/GridData", $scope.requestedItemsGridOptions)

Angular ui-route with JSON Data Request

I want to build a Single Page Website, where my data is stored in a CMS. This CMS accepts Ajax Requests to serve me JSON. This JSON I want to output in my ng-app using the ui-router (I also tried the ngRoute before, with same results).
The Problem is: I need no template. Cause all my data I need comes from the JSON Request. But using no template or templateUrl doesn't affects the controller.
The question is how to output my received data in the HTML? I cant use ng-controller because it binds on only this specific controller. Console.log shows that my data is successfully received, but I found no way to get an output.
app.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise("/");
$stateProvider
.state('state1', {
url: '/state1',
template: '<h1>This Is A State</h1>',
controller: function($scope, $http) {
$scope.pageObj = '';
$scope.pageObj.url = '/angular/demo/';
$scope.pageObj.class = 'page-my';
$scope.pageObj.data = 'Empty';
$http
.get('/angular/demo/')
.then(function(result) {
console.log("Data Received");
console.log(result.data);
$scope.pageObj.data = result.data;
});
//console.log(result.data);
console.log("Hello state");
}
});
});
I found a small solution with using factory. The question is still, how do I access my data? Data now is stored by an own controller i guess. I post my updated code below:
var app = angular.module('myApp', ['ngSanitize', 'ngRoute', 'ui.router']).factory("dataService", function($http) {
var data = "";
var getData = function() {
return data;
}
var setData = function(newData) {
data = newData;
}
return {
getData: getData,
setData: setData
};
});
app.controller('FactoryCtrl', ['$scope', '$http', 'dataService', function($scope, $http, dataService) {
$scope.mydata = dataService.getData();
console.log($scope.mydata);
}]);
app.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise("/");
$stateProvider
.state('state1', {
url: '/state1',
template: '<h1>{{pageObj.data}}</h1>',
controller: function($scope, $http, dataService) {
$scope.pageObj = '';
$scope.pageObj.url = '/angular/demo/';
$scope.pageObj.class = 'page-my';
$scope.pageObj.data = 'Empty';
$http
.get('/angular/demo/')
.then(function(result) {
console.log("Data Received");
$scope.pageObj.data = result.data;
//$scope.model.data = dataService.getData();
dataService.setData("a string");
//console.log(dataService.getData());
});
console.log("Hello state");
}
});
});

How to use an angular factory correctly?

I've been doing quite a lot of reading about angular dependency injection and factories vs services etc like in this post here - angular.service vs angular.factory
I'm struggling putting it into practise and wonder if you can give me suggestions on how you would do it.
My current code looks like this
var app = angular.module("martysCoolApp", ['firebase', 'ngRoute'])
function mainController($scope, $firebase) {
var db = new Firebase("https://**.firebaseio.com/");
$scope.messages = $firebase(db);
$scope.addItem = function(error) {
if (error.keyCode != 13) return;
$scope.messages.$add({ name: $scope.name, price: $scope.price });
$scope.name = "";
$scope.price = "";
};
}
I decided I wanted to use angular routes and split this basic function up into two different controllers that I would use for my test app. the MainController would just display everything in the firebase db and the AdminController would be able to add messages to it
var app = angular.module("martysCoolApp", ['firebase', 'ngRoute'])
.factory('fireBaseConnectionService', $firebase)
//code in here to connect to firebase and add messages
.controller('MainController', function(fireBaseConnectionService, $scope, $route, $routeParams, $location) {
$scope.$route = $route;
$scope.$location = $location;
$scope.$routeParams = $routeParams;
//code here to retrieve everything from firebase db
})
.controller('AdminController', function(fireBaseConnectionService, $scope, $routeParams) {
$scope.name = "AdminController";
$scope.params = $routeParams;
//code here to add a row to the db
})
.config(function($routeProvider, $locationProvider) {
$routeProvider.when('/', {
redirectTo: '/menu'
})
.when('/menu', {
path: '/menu',
templateUrl: 'partials/menu.html',
controller: 'MainController'
})
.when('/admin', {
templateUrl: 'partials/admin.html',
controller: 'AdminController'
})
.otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(false);
});
My problem is I don't want to have to connect to the firebase db in each controller. I would like to have a factory that handles this for me and has maybe functions within that that I can call from my controllers to view everything in db and to add something to the db
factory()
As we’ve seen, the factory() method is a quick way to create and configure a service.
The factory() function takes two arguments:
• name (string)
This argument takes the name of the service we want to register.
• getFn (function)
This function runs when Angular creates the service.
angular.module('myApp')
.factory('myService', function() {
return {
'username': 'auser'
}
});
The getFn will be invoked once for the duration of the app lifecycle, as the service is a singleton
object. As with other Angular services, when we define our service, getFn can take an array or a
function that will take other injectable objects.
The getFn function can return anything from a primitive value to a function to an object (similar to
the value() function).
angular.module('myApp')
.factory('githubService', [
'$http', function($http) {
return {
getUserEvents: function(username) {
// ...
}
}
}]);
service()
If we want to register an instance of a service using a constructor function, we can use service(),
which enables us to register a constructor function for our service object.
The service() method takes two arguments:
• name (string)
This argument takes the name of the service instance we want to register.
• constructor (function)
Here is the constructor function that we’ll call to instantiate the instance.
The service() function will instantiate the instance using the new keyword when creating the
instance.
var Person = function($http) {
this.getName = function() {
return $http({
method: 'GET',
url: '/api/user'
});
};
};
angular.service('personService', Person);
provider
These factories are all created through the $provide service, which is responsible for instantiating
these providers at run time.
angular.module('myApp')
.factory('myService', function() {
return {
'username': 'auser'
}
})
// This is equivalent to the
// above use of factory
.provider('myService', {
$get: function() {
return {
'username': 'auser'
}
}
});
Why would we ever need to use the .provider() method when we can just use the .factory()
method?
The answer lies in whether we need the ability to externally configure a service returned by the
.provider() method using the Angular .config() function. Unlike the other methods of service
creation, we can inject a special attribute into the config() method.
from ng-book
All you have to do is just move the firebase connection into the service, and inject that service wherever you want . The connection line will execute the first time your app runs, given that you front load the service when your app runs, as you seem to be doing now:
.factory('fireBaseConnectionService', function($firebase){
var db = $firebase(new Firebase("https://**.firebaseio.com/"));//creating
//the firebase connection this line executes only once when the service is loaded
return{
getMessage:function(){
return db.whatever;
}
}
})
If you load the service script dynamically, on route where you need it, it will only connect to the database when it reaches that route. The code above will create one connection to the database, as the connection line is executed only once.
Just for anyone interested with the help of the answers above and this link - Firebase _ AngularJS this is what I ended up doing
var app = angular.module("martysCoolApp", ['firebase', 'ngRoute'])
.factory('fireBaseConnectionService', ["$firebase", function($firebase) {
var db = new Firebase("https://***.firebaseio.com/");
return {
getMessages: function() {
return $firebase(db);
},
addMessage: function(message) {
var messages = $firebase(db);
messages.$add(message);
}
}
}])
.controller('MainController', ["fireBaseConnectionService", "$scope", function (fireBaseConnectionService, $scope, $route, $routeParams, $location) {
$scope.$route = $route;
$scope.$location = $location;
$scope.$routeParams = $routeParams;
$scope.messages = fireBaseConnectionService.getMessages();
}])
.controller('AdminController', ["fireBaseConnectionService", "$scope", function(fireBaseConnectionService, $scope, $routeParams) {
$scope.name = "AdminController";
$scope.params = $routeParams;
$scope.addItem = function(error) {
if (error.keyCode != 13) return;
fireBaseConnectionService.addMessage({ name: $scope.name, price: $scope.price });
$scope.name = "";
$scope.price = "";
}
}])
.config(function($routeProvider, $locationProvider) {
$routeProvider.when('/', {
redirectTo: '/menu'
})
.when('/menu', {
path: '/menu',
templateUrl: 'partials/menu.html',
controller: 'MainController'
})
.when('/admin', {
templateUrl: 'partials/admin.html',
controller: 'AdminController'
})
.otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(false);
});

Getting URL parameters using $route

I have the following url:
http://myurl.dev/users/32
I want to pass the last parameter 32 to a $http.get request but I can't figure out how to pass it.
So far I have this:
var matchmaker = angular.module('matchmaker', ['ngRoute'], function($interpolateProvider) {
$interpolateProvider.startSymbol('[[');
$interpolateProvider.endSymbol(']]');
})
.controller('LocationCtrl', ['$scope', '$http', '$location', '$routeParams', '$route', function($scope, $http, $location, $routeParams, $route) {
var id = $route.current.params.id;
console.log(id);
$http.get('http://myurl.dev/services/' + id ).success(function(data)
{
$scope.applicants = data;
});
}]);
In the console it's saying:
Cannot read property 'params' of undefined
Can anyone tell me what I'm doing wrong please?
Edit:
Angular isn't generating the url, it's a server side generated url
Edit 2.0
Here's the config for the routeProvider with actual route parameters:
var matchmaker = angular.module('matchmaker', ['ngRoute'], function($interpolateProvider) {
$interpolateProvider.startSymbol('[[');
$interpolateProvider.endSymbol(']]');
})
.config(function($routeProvider, $locationProvider) {
$routeProvider.when('/matchmaker/locations/:id', {
controller: 'LocationCtrl'
});
$locationProvider.html5Mode(true);
});
Put a console.log($routeParams); in your controller and check its value.
If it is Object {} check if you have a route definition using parameters:
var module = angular.module('ngRouteExample', ['ngRoute']);
module.config(function($routeProvider, $locationProvider) {
$routeProvider.when('/test/:id', {
templateUrl: 'test.html',
controller: 'TestController'
});
// configure html5 to get links working on jsfiddle
$locationProvider.html5Mode(true);
});
If so, you will get this output in the console:
Object {id: "42"}
It is because you trying to get value which doesn't exist at that moment, that's how javascript works. You need to specify that you want these values when they are ready using '$routeChangeSuccess' event.
.controller('PagesCtrl', function ($rootScope, $scope, $routeParams, $route) {
//If you want to use URL attributes before the website is loaded
$rootScope.$on('$routeChangeSuccess', function () {
//You can use your url params here
$http.get('http://myurl.dev/services/' + $routeParams.id )
.success(function(data) {
$scope.applicants = data;
});
});
});

AngularJS duplicates http requests

I'm doing some interfaces with AngularJS and watching the Chrome Console I detect that each http request to an API it makes for duplicate.
Is there any way to avoid this?
This is my simplified code
$http.jsonp('http://APIURL.com/api/category/menu?callback=JSON_CALLBACK').success(function(data){
$scope.categories=data.categories;
});
Full code:
var kbControllers = angular.module('kbControllers', []);
kbControllers.controller("KBHomeController", function ($scope, $http, $rootScope) {
$rootScope.header = 'Title of page';
$http.jsonp('apicall.com/api/category/menu?callback=JSON_CALLBACK').success(function (data) {
$scope.categories = data.categories;
});
});
and this is my console
any thought?
i have faced this problem, and you can resolve it like this :
check if you have declared ng-controller twice , you need to declare it just one time
check if you have declared data-ng-click , if so , you need to replace it with ng-click
that's it
This is app.js
var app = angular.module('app', [
'ngRoute','kbControllers', 'kbFilters', 'kbDirectives', 'angularytics', 'kbServices'
]).config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/',
{
templateUrl: '/assets/angular/kb/partials/home.html',
controller: 'KBHomeController'
}
).when('/category/:category',
{
templateUrl: '/assets/angular/kb/partials/category.html',
controller: 'KBCategoryController'
}
)
.otherwise({redirectTo:"/"});
}
])
And in controllers.js
var kbControllers = angular.module('kbControllers', []);
kbControllers.controller("KBHomeController", function ($scope, $http, $rootScope, Menu) {
$rootScope.header = 'Atención al cliente - Movistar Argentina';
$http.jsonp('http://APIURL.com/api/category/menu?callback=JSON_CALLBACK').success(function(data){
$scope.categories=data.categories;
});
})
and my view /partials/home.html
[...]
<li ng-repeat="category in categories"><i class="{{category.icon}}"></i><span>{{category.name}}</span></li>
[...]

Categories