I'm building an application in Rails and I'm using Angular for part of the front end, generating views based on data provided in a json file. I've been following this tutorial, but I can't seem to get my controller to run and I have no idea why. Can anyone help me out?
Sample link: http://localhost:3000/events/events1
events.coffee.erb
app = angular.module('EventsApp', ['ui.router', 'templates'])
app.config [
'$stateProvider'
'$urlRouterProvider'
($stateProvider, $urlRouterProvider) ->
$stateProvider.state 'events',
url: '/events/{id}'
templateUrl: 'templates/_event.html'
controller: 'EventsCtrl'
]
app.controller 'EventsCtrl', [
'$scope'
'$stateParams'
($scope, $stateParams) ->
console.log $stateParams //this never shows up
console.log 'Sup' //this never shows up
$scope.greeting = 'Yo' //neither does this
]
events.html.erb
<div ng-app="EventsApp">
Yo! //this shows up, but not {{greeting}}
{{greeting}}
<ui-view></ui-view>
</div>
_event.html
<script type="text/ng-template" id="/event.html">
<div>
{{greeting}}
Yo!
</div>
</script>
Rails routes file:
get "events/*path" => "events#events"
Rails events_controller.rb
class EventsController < ApplicationController
layout "application"
def events
end
end
File layout:
--app
-----assets
-------javascripts
----------templates
------------_event.html
----------events.coffee.erb
------views
--------events
----------events.html.erb
Your angular code is poorly structured. I think you are mixing up your Javascript syntax with your Ruby syntax...
Try something closer to this:
angular.module('EventsApp', ['ui.router', 'templates'])
.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider.state('events', {
url = '/events/{id}',
templateUrl: 'templates/_event.html',
controller: 'EventsCtrl'
}
}
])
.controller('EventsCtrl', [
'$scope', '$stateParams'
function($scope, $stateParams) {
console.log($stateParams);
console.log('Sup')
$scope.greeting = 'Yo';
}
]);
Related
I've been struggling with getting my AngularJS app to display a view based on a template.
The issue: ui-router seems to be correctly "routing" all the files, because the template file (landing.html) is being delivered to the console as an object (see console.log(result) in main.js below). Nevertheless, the template file is not being displayed in the app where <div ui-view></div> is supposed to be.
index.html:
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
##include('partials/head.html')
<body>
##include('partials/header.html')
<div ui-view></div>
##include('partials/footer.html')
</body>
</html>
main.js:
angular.module('myApp', [
'ui.router'
])
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('landing', {
url: '/',
controller: 'LandingCtrl as landing',
templateUrl: 'templates/landing.html'
});
$urlRouterProvider.otherwise('/landing');
}])
.run(['$http', '$templateCache', function($http, $templateCache) {
$http.get('templates/landing.html', {
cache: $templateCache
}).then(function(result) {
console.log(result);
});
}]);
My template file landing.html:
<main class="content">
##include('partials/search.html')
<h2>Show me the contents of landing.html!</h2>
</main>
I'm using grunt and made sure to have it both watch and copy the /templates into /dist. Overall the Angular app is behaving correctly (no ng errors in the console).
Also, if instead of specifying a template file (templateURL), I simply use template: <h2>Show me the contents of landing.html!</h2> in main.js then this is rendered in the view. There's something preventing a file from being rendered.
Question: Given ui-router is correctly finding and routing all files, does anyone have an idea as to why the app is simply not displaying the template file?
Edit Here is LandingCtrl.js:
(function() {
function LandingCtrl($scope, $location, $anchorScroll) {
$scope.goTo = function(id) {
$location.hash(id);
console.log($location.hash());
$anchorScroll();
};
}
angular
.module('myApp')
.controller('LandingCtrl', ['$scope', '$location', '$anchorScroll', LandingCtrl]);
})();
in your main.js file change the url of Landing State as below:
angular.module('myApp', [
'ui.router'
])
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('landing', {
url: '/landing',
controller: 'LandingCtrl as landing',
templateUrl: 'templates/landing.html'
});
$urlRouterProvider.otherwise('/landing');
}])
.run(['$http', '$templateCache', function($http, $templateCache) {
$http.get('templates/landing.html', {
cache: $templateCache
}).then(function(result) {
console.log(result);
});
}]);
I'm trying to split my angularjs controllers into files but failing everytime.
Directory Structure:
--public--
--js/controller/resturant.js
--js/master.js
--index.php
Code for master.js
angular.module("rsw",['rsw.controller']);
Code for resturant.js
angular.module('rsw.controller').controller('resturant', ['$scope', '$http', function($scope, $http){
$scope.data="Test"
}]);
Code for index.php
--
<div ng-app="rsw">
<span ng-controller="resturant">
{{ data }}
</span>
</div>
--
EDIT:
I've included only 'master.js' in my index.php, do I need to import 'resturant.js" too?
You need to use the correct module definition call. That is, angular.module(name) retrieves a module and angular.module(name, [requires]) creates one.
angular.module('rsw.controller', [])
.controller('resturant', ['$scope', '$http', function($scope, $http){
$scope.data="Test"
}]);
After creating your module, you need to then make it a dependency of your app:
angular.module("rsw",['rsw.controller']);
Fixed code:
angular.module("rsw", ['rsw.controller']);
angular.module('rsw.controller', [])
.controller('resturant', ['$scope', '$http',
function($scope, $http) {
$scope.data = "Test"
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="rsw">
<span ng-controller="resturant">
{{ data }}
</span>
</div>
I think you had set up your controller wrong.
Try typing this instead:
angular.module('rsw').controller('resturant', ['$scope', '$http', function($scope, $http){
$scope.data="Test"
}]);
something like this should work...
file structure:
--public
--js
--controllers
--resturant.js
--app.js
--appRoutes.js
--views
--index.php
// resturant.js
angular.module('rswCtrl', []).controller('RswController', [$scope, function($scope) {
}]);
// appRoutes.js
angular.module('appRoutes', []).config(['$routeProvider','$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/index.php',
controller: 'RswController'
});
}]);
// app.js
angular.module('myApp', ['appRoutes', 'rswCtrl']);
and then don't forget to include paths to all these files in your index.php file. Hope I'm not missing something..
I am trying to have a link in my page such as:
<a ng-href="#/Page/{{x.ID}}">{{x.ID}}</a>
Which succesfully gets to the angular controller but however the $routeparams are null when I am expecting to get the {{ x.ID }} back:
pageController.js
angular.module("myApp.Pages").controller("pageController", ['$scope', '$http', '$routeParams', function ($scope, $http, $routeParams) {
console.log($routeParams);
}]);
And am referencing the state in my $stateprovider such as (in appRouting.js):
$stateprovider.state('Page', {
url: '/Page/:userId',
templateUrl: 'App/Pages/page.html',
controller: 'pageController'
})
my app.js
angular.module("myApp", [
// User defined modules
'myApp.Pages', // Pages
'myApp.Core', // Core
// Angular modules
'ui.router', // state routing
'ngRoute', // angular routing
'LocalStorageModule', //local browser storage
'angularRangeSlider',
'ngFileUpload'
])
Any ideas?
$stateParams instead of $routeParams
I have a project where homeapp.js contains the angular.module dependencies:
var HomeApp = angular.module('HomeApp', [
'ngRoute',
'ngCookies',
'HomeControllers',
'metadataControllers',
'MyControllers',
'ScheduleControllers'
]);
HomeApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/schedules', {
templateUrl: 'pages/list_schedule.html',
controller: 'ScheduleControllers'
});
and in a ScheduleController.js, I have:
angular.module('ScheduleControllers', []).controller('PhoneListCrl', function($scope) {
$scope.phones = [
{'name': 'Nexus S',
'snippet': 'Fast just got faster with Nexus S.'},
{'name': 'Motorola XOOM with Wi-Fi',
'snippet': 'The Next, Next Generation tablet.'},
{'name': 'MOTOROLA XOOM',
'snippet': 'The Next, Next Generation tablet.'}
];
});
this is basically the code snippet from the angular tutorial.
In the index.html, I have:
<html lang="en-CA" ng-app="HomeApp">
...
<li id="id_schedule_list" class="header_list">List Schedule</li>
...
which then directs to this the schedules.html with only the follow codes:
<div>
<div ng-controller="PhoneListCrl">
<p>{{phones}}</p>
</div>
</div>
However when the html is opened from browser, it shows {{phones}} straight, without being able to show the full json object. The console says
https://docs.angularjs.org/error/ng/areq?p0=ScheduleControllers&p1=not%20a 1.#QNAN0unction%2C%20got%20undefined
Which doesn't really make sense to me, but I guess it is saying ScheduleControllers is undefined.
EDIT:
In angluar's tutorial, the app.js says:
var phonecatApp = angular.module('phonecatApp', [
'ngRoute',
'phonecatAnimations',
'phonecatControllers',
'phonecatFilters',
'phonecatServices'
]);
and then in controllers.js, it has:
var phonecatControllers = angular.module('phonecatControllers', []);
phonecatControllers.controller('PhoneListCtrl', ['$scope', 'Phone',
function($scope, Phone) {
$scope.phones = Phone.query();
$scope.orderProp = 'age';
}]);
Looks like I am almost doing exactly what the tutorial does, but why it doesn't work for me?
The problem is actually with the route. You are using the module's name for the controller instead of the actual controller name.
Where you have controller: 'ScheduleControllers', you instead need controller: 'PhoneListCtrl'. Additionally, the code you pasted has a typo in the controller definition. You need a t in PhoneListCtrl in
angular.module('ScheduleControllers', []).controller('PhoneListCtrl', function($scope) `
EDIT
In the following code, you are telling angular which controller to load when you access the /schedules route. Right now, it is pointing to 'ScheduleControllers', which is a module, not a controller. Change it to match the second block and you should be good to go.
HomeApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/schedules', {
templateUrl: 'pages/list_schedule.html',
controller: 'ScheduleControllers'
});
HomeApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/schedules', {
templateUrl: 'pages/list_schedule.html',
controller: 'PhoneListCtrl'
});
See https://docs.angularjs.org/tutorial/step_07 for reference.
You're attaching your controller to another Angular module:
// This line creates a new module named "ScheduleControllers"
// And attaches the "PhoneListCrl" to it.
angular.module('ScheduleControllers', []).controller('PhoneListCrl', function() { ... });
If you want it to be visible to your HomeApp then attach it to that module:
// You need to attach "PhoneListCrl" to your original module.
angular.module('HomeApp').controller('PhoneListCrl', function() { ... });
the controller: 'ScheduleControllers' is name of module and not controller, hence the issue
I'd like the root URL, /, of my AngularJS app to display a template based on cookie value. For example, when a login cookie is present display dashboard. When login cookie is absent, display a login screen.
I tried to inject $cookies to app.config to determine the template property of $route based on it, but that didn't work.
var myApp = angular.module('myApp', ['ngRoute', 'ngCookies']);
myApp.config([
'$routeProvider',
'$locationProvider',
function ($routeProvider, $locationProvider) {
$routeProvider.
when('/', {
templateUrl: function() {
// read cookies here?
return '../../connect.html';
},
controller: "getAuthUrl"
});
$locationProvider.
html5Mode(true).
hashPrefix('!');
}
]);
Answering my own question...
After further investigation, I found out that $routeProvider is not what I should be using. $routeProvider is for serving templates based on URL routes. What this problem needed is the ui-router module, which is an official AngularJS module.
Instead of URLs, ui-router lets you specify page content based on "state". In my situation, I have a "loggedin" state and a "dashboard" state. Here's how I have implemented the solution:
var myApp = angular.module('myApp', ['ngCookies', 'ui.router']);
myApp.config([
'$stateProvider',
'$locationProvider',
function ($stateProvider, $locationProvider) {
$stateProvider.
state('login', {
template: '<h1>Login now.</h1>'
}).state('dashboard', {
template: '<h1>You are logged in. Welcome.</h1>'
});
$locationProvider.
html5Mode(true).
hashPrefix('!');
}
]);
myApp.controller('mainCtrl', [
'$scope',
'$state',
'$cookies',
function($scope, $state, $cookies) {
// You can read cookies here
if (true) {
console.log($cookies);
$state.go('dashboard');
}
else {
$state.go('login');
}
}
]);
And then the HTML is
<!DOCTYPE html>
<html ng-app='myApp'>
<head>
<script src='js/lib/angular.js'></script>
<script src='js/lib/angular-ui-router.js'></script>
<script src='js/lib/angular-cookies.js'></script>
<script src="js/app.js"></script>
</head>
<body ng-controller='mainCtrl'>
<div class="container" ui-view></div>
</body>
</html>
You can read all about ui-router in its wiki
Note: You have to use ui-router v0.0.2 at least. v0.0.1 won't work.