Data not binding in route? - javascript

I am stuck in the last part of this Codecademy AngularJs project
I have used routing and the routing works (it changes the view when clicked), but doesn't show data binding. I have checked index.html so I don't think there's a mistake there. Could you please check it? Here is the code:
app.js
var app = angular.module('CalendarApp', ['ngRoute'])
app.config(['$routeProvider', function($routeProvider) {
$routeProvider .when('/', {
controller: 'DayController',
templateUrl: 'views/day.html'
}).when('/:id',{
controller: 'EventController',
templateUrl: 'views/event.html'
}).otherwise({
redirectTo: '/'
});
}]);
events.js (Service)
app.factory('events', ['$http', function($http) {
return $http.get('https://s3.amazonaws.com/codecademy-content/courses/ltp4/events-api/events.json').success(function(data) {
return data;
}).error(function(err) {
return err;
});
}]);
EventController.js
app.controller('EventController', ['$scope', 'events', '$routeParams', function($scope, $routeParams, events) {
$scope.eventId = $routeParams.id;
events.success(function(data) {
$scope.event = data.events;
});
}]);
event.html (view)
<div class="event-detail">
<h2 class="event-name">{{event[eventId].name}}</h2>
</div>
And here's the short format of events.json whose data I'm trying to get:
{
"date": 1421384400000,
"events": [
{
"name": "Casual Friday",
"from": 1421384400000,
"to": 1421470800000,
"where": ""
},
{
"name": "Taco Time",
"from": 1421431200000,
"to": 1421438400000,
"where": "Brooklyn Taco Co. 120 Essex Street New York, NY 10002"
}
]
}

events.js
try returning promise, but load it only once;
app.factory('events', ['$http', function($http) {
var promise = $http.get('https://s3.amazonaws.com/codecademy-content/courses/ltp4/events-api/events.json');
return {
getEvents : function(){ return promise; }
}
}]);
Now if you console.log it you should recieve Promise object in your controller.
EventController.js
app.controller('EventController', ['$scope', 'events','$routeParams', function($scope, events, $routeParams) {
// code in regards to itemId etc.
events.getEvents().then(function(d){
$scope.event = d.data.events;
});
}]);
(considering rest of the functionality works as you mentioned)
Let me know if it works

Related

Resolve function not being injected in controller [Angular JS]

angular
.module('madkoffeeFrontendApp', [])
.config(function ($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/articles.html',
controller: 'MainCtrl',
resolve: {
articles: function(articleService,$q) {
// return articleService.getArticles();
return 'boo';
}
}
})
.otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(true);
});
My above code contains the resolve.
angular.module('madkoffeeFrontendApp')
.controller('MainCtrl', ['$scope',
function($scope, articles) {
console.log(articles);
}]);
When I tried to inject articles in the array as shown below, it gives an error but as far as I know that's the correct way to inject a resolve function:
angular.module('madkoffeeFrontendApp')
.controller('MainCtrl', ['$scope','articles',
function($scope, articles) {
console.log(articles);
}]);
My articles resolve function is not being injected. I tried returning just a string (example: 'boo') as shown to test if articles dependency works or not, and it doesn't i.e. it returns undefined. What could be the reason?
Here's a Plunker to demonstrate the resolve message. As you'll see in the example, it's the same structure as the code you posted and should work fine.
Click the about page to see the resolve message.
http://plnkr.co/edit/FomhxYIra5GI7nm1KpGb?p=preview
Code:
var resolveTestApp = angular.module('resolveTestApp', ['ngRoute']);
resolveTestApp.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl : 'pages/home.html',
controller : 'mainController'
})
.when('/about', {
templateUrl : 'pages/about.html',
controller : 'aboutController',
resolve: {
resolveMessage: function() {
return 'This is the resolve message';
}
}
})
});
resolveTestApp.controller('mainController', function($scope) {
$scope.message = 'Everyone come and see how good I look!';
});
resolveTestApp.controller('aboutController', ['$scope', 'resolveMessage', function($scope, resolveMessage) {
$scope.message = resolveMessage;
}]
);
It may be the version of Angular you're using or a problem when you're minifying your code.

angular unknown provider error using factory and ui.router resolve

I'm getting unknown provider error when i'm trying to use resolve from a state. The object i want returned seems to be returned correctly, so i can't really figure out what the problem is.
This is my first angular project so if I something seems wierd it probably is.
The error: https://docs.angularjs.org/error/$injector/unpr?p0=boardProvider%20%3C-%20board%20%3C-%20AppCtrl
var ponk = angular.module("ponk", ["ui.router", "ngResource"]);
ponk.config(['$stateProvider', '$urlRouterProvider',
"$locationProvider", function ($stateProvider, $urlRouterProvider,
$locationProvider) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/');
$stateProvider.state('board', {
url: '/b/:slug',
templateUrl: 'views/board.html',
controller: "AppCtrl",
controllerAs: "pk",
resolve: {
board: function($stateParams, boardFactory) {
var board = {};
if($stateParams.slug) {
board = boardFactory.get({slug:$stateParams.slug}).$promise;
}
return board;
}
}
});
}]).run(function($state) { $state.go('board'); });;
ponk.factory("boardFactory", ["$http", "$resource",
function($http, $resource) {
return $resource('/board/:slug', {slug:'slug'}, {update: { method: "PUT" }});
}]);
ponk.controller("AppCtrl", ["$scope", "$http", "boardFactory", "board",
function($scope, $http, boardFactory, board ) {
console.log(board); // correct object, but error
}]);
EDIT:
discovered the above code works. The problem is when i add this to the controller:
var pk = this;
var pk.board = board;

$state.go doesn't work with ng-click

When an item is clicked, its path is sent as parameter to state function and the state function does $state.go to load a state with the passed path as parameter.
This doesn't seem to work. What am I missing here?
Template
<div ng-click="state(item.class, item.path, item.mime_type)">
Controller
controller("groupsListCtrl", ["$scope", "handler", "$state",
function($scope, handler, $state) {
handler.get("/home").then(function(response) {
$scope.data = response;
$scope.items = $scope.data.inventory;
$scope.state = function(stateType, objectPath, mimeType) {
$state.go("workarea.user", {
path: objectPath
});
}
})
}
])
Router
.state("workarea.user", {
url: "^/workarea/:path",
requireLogin: true,
views: {
"options": {
templateUrl: "/views/options.html",
controller: "optionsCtrl"
},
"workspace": {
templateUrl: "/views/workspace.html",
controller: "workspaceCtrl"
},
"comments": {
templateUrl: "/views/comments.html",
controller: "commentsCtrl"
}
}
});
handler.get("/home").then(function(response) { looks like a promise to me.
Try moving $scope.state definition outside this promise.
controller("groupsListCtrl", ["$scope", "handler", "$state",
function($scope, handler, $state) {
handler.get("/home").then(function(response) {
$scope.data = response;
$scope.items = $scope.data.inventory;
});
$scope.state = function(stateType, objectPath, mimeType) {
$state.go("workarea.user", {
path: objectPath
});
}
}
])

Separating my Controller and Factory from App.js - AngularJS

Trying to separate my Controllers and Factories from out of my large app.js file. I learned Angular by putting everything into one file, but now I am trying to organize it all by separating my files.
Originally I had something like this (app.js).
var app = angular.module("app", ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'pages/home.html',
controller: 'HomeController'
})
.when('/home', {
templateUrl: 'pages/home.html',
controller: 'HomeController'
})
.when('/faq', {
templateUrl: 'pages/faq.html',
controller: 'FAQController'
})
.otherwise({
redirectTo: '/unknown'
});
});
app.factory('FAQMethodService', function() {
return {
faqs: [
{
question : "Another FAQ",
answer : "Another FAQ."
},
{
question : "Another FAQ",
answer : "Another FAQ."
},
{
question : "Another FAQ",
answer : "Another FAQ."
},
{
question : "Another FAQ",
answer : "Another FAQ."
}
]
};
});
app.controller('FAQController', function($scope, FAQMethodService) {
$scope.faqList = FAQMethodService.faqs;
$scope.title = "FAQ";
});
app.controller('HomeController', function($scope) {
$scope.title = "Home";
});
For my first step of separation I deleted the section of FAQController from app.js, and made a new file called faqController.js (which I included in my index.html).
angular.module('app').controller('FAQController', ['$scope', '$http', function($scope, FAQMethodService) {
$scope.faqList = FAQMethodService.faqs;
$scope.title = "FAQ";
}]);
When I open my FAQ page I get the $scope.title variable (as I display it), but my FAQMethodService information does not show up.
Question: How can I get my Factory when my Controller is in another file (and can I separate my Factory to another file too)?
When registering things using the array notation, the names and sequence of string arguments must match exactly with the sequence of the constructor function's parameters.
You have a mismatch. You've asked Angular to inject $http into your controller as FAQMethodService
.controller('FAQController', ['$scope', '$http', function($scope, FAQMethodService) {
It should be:
.controller('FAQController', ['$scope', 'FAQMethodService', function($scope, FAQMethodService) {

Angular js display name based on selected item and url path

I am starting out on the angular seed. I have a json file that displays items like the below.
{
"id":"1",
"name":"Spain",
"abbrev":"esp"
}
When I click on a country in the list I want to the display the details such as the name for this item.
I have this working as shown below.
/* app.js */
'use strict';
// Declare app level module which depends on views, and components
angular.module('myApp', ['ngRoute','myApp.controllers','myApp.services'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/', {
templateUrl: 'templates/view1.html',
controller: 'CountryCtrl'
});
}])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/:name', {
templateUrl: 'templates/view2.html',
controller: 'CountryCtrl'
});
}])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.otherwise({redirectTo: '/'});
}]);
/* services.js */
angular.module('myApp.services', [])
.factory('Countries', ['$http', function($http) {
var Countries = {};
Countries.name = '';
Countries.listCountries = function () {
return $http.get('../api/countries');
},
Countries.ChangeName = function (value) {
Countries.name = value;
}
return Countries;
}]);
/* controllers.js */
angular.module('myApp.controllers', [])
.controller('CountryCtrl', ['$scope', 'Countries', '$location', function($scope, Countries,$location) {
listCountries();
function listCountries() {Countries.listCountries()
.success(function (data, status, headers, config) {
$scope.countries = data.countries;
})
.error(function(data, status, headers, config) {
$scope.status = 'Unable to load data: ' + error.message;
});
}
$scope.name = Countries.name;
$scope.changeView = function(countryName,indx){
$location.path(countryName);
$scope.name = Countries.ChangeName(countryName);
}
}]);
/* templates/view1.html */
<ul>
<li ng-repeat="country in countries">
<div ng-click="changeView(country.name,$index)">{{country.name}}</div>
</li>
</ul>
/* templates/view2.html */
{{name}}
What I can't get to work is that if I go to http://www.example.com/app/#/ then navigate to spain in the list then I get taken to http://www.example.com/app/#/esp and {{name}} gets outputted as esp.
However if I navigate straight to http://www.example.com/app/#/esp without first clicking on spain in the list I get no value in my $scope.name
How can I achieve this?
I want the name to also be set based on the location path if it is available.
I know that $location.$$path will get me /esp however I don't really think this is the best idea to use this incase the url builds out to something bigger eg http://www.example.com/app/#/esp/events
can I some how access the index or id of the item so that I can then access the data like
{{countries[0].name}}
where 0 is id of esp - 1.
What is the best approach?
Mate, there are a couple of issues with your app.
Your service retains "state" although is only used to retrieve information
You're using the same controller to 2 different views (bad practice)
$scope.status = 'Unable to load data: ' + error.message; --> Error is not defined
There are a couple of js errors too, like strayed commas and stuff
Anyways, here's a revised version of your code. Fiddle
// Instantiate your main module
var myApp = angular.module('myApp', ['ngRoute']);
// Router config
myApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'templates/view1.html',
controller: 'CountryListCtrl'
})
.when('/:id', {
templateUrl: 'templates/view2.html',
controller: 'CountryCtrl'
})
}
]);
// Your Factory. Now returns a promise of the data.
myApp.factory('Countries', ['$q',
function($q) {
var countriesList = [];
// perform the ajax call (this is a mock)
var getCountriesList = function() {
// Mock return json
var contriesListMock = [{
"id": "0",
"name": "Portugal",
"abbrev": "pt"
}, {
"id": "1",
"name": "Spain",
"abbrev": "esp"
}, {
"id": "2",
"name": "Andora",
"abbrev": "an"
}];
var deferred = $q.defer();
if (countriesList.length == 0) {
setTimeout(function() {
deferred.resolve(contriesListMock, 200, '');
countriesList = contriesListMock;
}, 1000);
} else {
deferred.resolve(countriesList, 200, '');
}
return deferred.promise;
}
var getCountry = function(id) {
var deferred = $q.defer();
if (countriesList.length == 0) {
getCountriesList().then(
function() {
deferred.resolve(countriesList[id], 200, '');
},
function() {
deferred.reject('failed to load countries', 400, '');
}
);
} else {
deferred.resolve(countriesList[id], 200, '');
}
return deferred.promise;
}
return {
getList: getCountriesList,
getCountry: getCountry
};
}
]);
//Controller of home page (pretty straightforward)
myApp.controller('CountryListCtrl', ['$scope', 'Countries',
function($scope, Countries) {
$scope.title = 'Countries List';
$scope.countries = [];
$scope.status = '';
Countries.getList().then(
function(data, status, headers) { //success
$scope.countries = data;
},
function(data, status, headers) { //error
$scope.status = 'Unable to load data:';
}
);
}
]);
// controller of Country page
// Notice how we use $routeParams to grab the "id" of our country from the URL
// And use our service to look for the actual country by its ID.
myApp.controller('CountryCtrl', ['$scope', '$routeParams', 'Countries',
function($scope, $routeParams, Countries) {
$scope.country = {
id: '',
name: '',
abbrev: ''
};
var id = $routeParams.id;
Countries.getCountry(id).then(
function(data, status, hd) {
console.log(data);
$scope.country = data;
},
function(data, status, hd) {
console.log(data);
}
);
}
]);
In your "CountryCtrl", if you include $routeParams and use $routeParams.tlaname, you will have access to the tlaname. You can then use that to initialize your data.

Categories

Resources