I have a question I would like to ask the community, but am having trouble setting up the required JSFiddle to make it easier to demonstrate the issue. I want to create a fiddle with three views side by side using Angular's ui-router. Seems simple, but for some reason I can't get the views' controller's to initialize. The main app loads, as evidenced by console messages, but I'm stumped.
The Fiddle is here, and for completeness sake, the html and js are here:
HTML:
<div ui-view="top" class="top">
<br />
$scope.testmsg = {{testmsg}}
<br />
$scope.statename = {{statename}}
<br />
top!
</div>
<div ui-view="middle" class="middle">middle!</div>
<div ui-view="bottom" class="bottom">bottom!</div>
JS:
/* myApp module */
var myApp = angular.module('myApp', ['ui.router'])
.config(['$stateProvider', function ($stateProvider) {
$stateProvider.state('home', {
url: "/",
views: {
'top': {
url: "",
template: '<div>top! {{topmsg}}</div>',
controller: function ($scope) {
$scope.topmsg = "loaded top!";
console.log("top ctrl!"); // this does NOT show in console
}
},
'middle': {
url: "",
template: '<div>middle! {{middlemsg}}</div>',
controller: function ($scope) {
$scope.middlemsg = "loaded middle!";
console.log("middle ctrl!"); // this does NOT show in console
}
},
'bottom': {
url: "",
templateUrl: '<div>bottom! {{bottommsg}}</div>',
controller: function ($scope) {
$scope.bottommsg = "loaded bottom!";
console.log("bottom ctrl!"); // this does NOT show in console
}
}
},
onEnter: function () {
console.log("entered home state"); // this does NOT show in console
}
});
}])
.controller('MyAppCtrl', function ($scope, $state/*, $stateParams*/) {
$scope.statename = $state.current.name;
$scope.testmsg = "app scope working!";
console.log("MyAppCtrl initialized!"); // this shows in console
$state.go("home");
});
My body tag has the correct (I believe) references to my app and controller: <body ng-app="myApp" ng-controller="MyAppCtrl"></body>... I'm stuck. Any help would be great.
Thanks in advance!
I think your only mistake is in the configuration for the 'bottom' view. You have templateUrl instead of template. After I made this change in your fiddle, all the controllers initialize correctly.
Here's an updated fiddle. But like I said, changing templateUrl to template is the only change. Hope this helps!
Related
I am having strange results working with AngualarJS states. Here is app code:
/* myApp module */
var myApp = angular.module('myApp', ['ui.router'])
.config(function ($stateProvider) {
$stateProvider.state('home', {
url: "home",
template: '<div ui-view><h3>Home</h3><a ui-sref="home.child({reportID:1})">Child</a></div>',
params: { reportID: null },
controller: function ($scope) {
$scope.homeCtrlVar = "home";
console.log("Home controller loaded");
}
}).state('home.child', {
template: '<div><h3>Child</h3><a ui-sref="home">Back</a></div>',
controller: function ($scope) {
$scope.childCtrlVar = "child";
console.log("Child controller loaded");
}
});
})
.controller('MainCtrl', function ($scope, $state) {
console.log("MainCtrl initialized!");
$state.go("home");
});
And main page:
<div ng-app="myApp" ng-controller="MainCtrl">
<h2>My app</h2>
<div ui-view></div>
What's happening is that as long as there parameters for the home state and reportID value doesn't match between a parameter being sent and the state default the home controller is loaded when I click on Child. Can someone please explain why that's happening?
Fiddle
Here is updated code which works as you expect it to:
var myApp = angular.module('myApp', ['ui.router'])
.config(function ($stateProvider) {
$stateProvider.state('home', {
url: "home",
template: '<div ui-view><h3>Home</h3><a ui-sref="home.child({reportID:1})">Child</a></div>',
controller: function ($scope) {
$scope.homeCtrlVar = "home";
console.log("Home controller loaded");
}
}).state('home.child', {
url: "/:reportID",
params: { reportID: null },
template: '<div><h3>Child</h3><a ui-sref="home">Back</a></div>',
controller: function ($scope) {
$scope.childCtrlVar = "child";
console.log("Child controller loaded");
}
});
})
Problem with your approach:
specifying params reportID in home state instead of home.child state.
When user clicks on home.child({ reportId: 1}) it should load home.child, which is fine, and was working with old approach.
However, If you take notice, as you click on home.child({ reportId: 1}), you are sending new parameter reportID(old value was null). reportID belongs to home state, hence its controller is also loaded.
Note that url: "/:reportID" in state home.child is optional.
I am trying to build a link using routeParams of the route angularJs class. which works pretty well but for some reason it doesn't interpolate my strings.
I have tried the following:
{{username}} as in the controller i set $scope.username = $routeParams.username;
{{ Repo.username }} as the controller is called RepoController.
however both had no result except printing it as a string literal on the screen.my code is as below
App.js
(function() {
var app = angular.module("githubViewer", ["ngRoute"])
app.config(function($routeProvider) {
$routeProvider
.when("/main", {
templateUrl: "main.html",
controller: "MainController"
})
.when("/user/:username", {
templateUrl: "user.html",
controller: "UserController"
})
.when("/repo/:username/:reponame", {
templateUrl: "repo.html",
controller: "RepoController"
})
.otherwise({
redirectTo: "/main"
})
});
}());
RepoController.js
(function() {
var app = angular.module("githubViewer")
var RepoController = function($scope, github, $routeParams) {
$scope.username = $routeParams.username;
$scope.reponame = $routeParams.reponame;
app.controller("RepoController", ["$scope", "github", "$routeParams", RepoController]);
}());
Repo.html
<section>
{{ username }}
<br />
{{ repo.name }}
</section>
There is a plunker available:
https://plnkr.co/edit/oGJJOUfCqW8G7OAXxXGa?p=preview
thanks a lot for any help. Cheers!
There are a couple of syntactic and semantic issues in the Plunkr that may be affecting your actual code.
You have a syntax error in the RepoController.js -- you do not close the RepoController function declaration with }
You are not including <script src=RepoController.js> in index.html
$scope.repo is not an object with a name property. In your template, use reponame instead or you could do $scope.repo = {name: $routeParams.reponame}
Attempting to navigate to a child route of a parent route with a parameter. The ng-click does go off and I can see it in the console registering the click, but I get no changes to the state. Am I declaring the ui-sref wrong?
<body ng-controller="myController as $ctrl" style="{margin-top: 70px;}">
<div>
<button><a ui-sref="idLevel.index({something: 1})" ng-click="$ctrl.test()">Link1</a></button>
<button><a ui-sref="idLevel.other({something: 2})" ng-click="$ctrl.test2()">link2</a></button>
</div>
<ui-view>
<div>
test
</div>
</ui-view>
// Code goes here
function appRoute($stateProvider, $locationProvider) {
$locationProvider.html5Mode(false);
$stateProvider
.state('idLevel', {
url: '/:something',
abstract: true,
})
.state('idLevel.index', {
url: '/index/',
component: 'component1'
})
.state('idLevel.other', {
url: '/other/',
component: 'component2'
})
}
var component1 = {
template: '<h1>indexRoute</h1><br><p>HELP!!{{$ctrl.params}}</p>',
controller: function($stateParams) {
var ctrl = this;
console.log('component1', $stateParams);
ctrl.params = $stateParams.id;
}
};
var component2 = {
template: '<div><h1>otherRoute</h1><br><p>Help2 {{$ctrl.params}}</div>',
controller: function($stateParams) {
var ctrl = this;
console.log('component2', $stateParams);
ctrl.params = $stateParams.id;
}
};
function myController($stateParams) {
var ctrl = this;
ctrl.test = test;
ctrl.test2 = test2;
function test() {
console.log('TEST LINK!', $stateParams.id)
}
function test2() {
console.log('TEST 2', $stateParams.id)
}
}
angular.module('app', ['ui.bootstrap', 'ui.router'])
.config(appRoute)
.controller('myController', myController)
.component('component1', component1)
.component('component2', component2);
myController.$inject = ['$stateParams'];
appRoute.$inject = ['$stateProvider', '$locationProvider'];
component1.$inject = ['$stateParams'];
component2.$inject = ['$stateParams'];
Plnkr here
I feel like I'm missing something simple here, but I can't figure out why its not allowing me to hit the route.
A parent state needs to have a <ui-view> in it's template for child states to render in.
Note that in plunker you can't use / as base since the editor is not in the root of site
Updated plunker
firstly your plunkr looks a bit different to the code you've shown, secondly, from what I can see, the plunkr seems to be working - you are getting a state change - you cant see it because the content is hidden behind the title nav bar.
If you open the plunkr in the separate window (blue button) you can just see the content under the navbar changing as you click the links.
Context: I just got started with AngularJS, starting from a clean generator-angular-fullstack build. As part of the install I went with UI router.
I've set up server API endpoints and tested them in the browser. They all check out.
I'm trying to do a minimal http.post request to call those API endpoints. Via Yeoman I've pre-generated a new route 'signIn' in client/app/signIn (which includes signIn.html, signIn.js, signIn.controller.js, signIn.controller.spec.js, signIn.scss).
Here is what I'm working from:
signIn.html
<script>
var MainCtrl = function($scope, $http) {
$http.post('/api/auth/signin', {auth_token: '5'}).success(function(response) {
$scope.response = response;
});
};
</script>
<body ng-controller="MainCtrl">
<section ui-view>Response: {{response}}</section>
</body>
For completeness (still untouched:)
signIn.js
'use strict';
angular.module('orbitApp')
.config(function ($stateProvider) {
$stateProvider
.state('signIn', {
url: '/signIn',
template: '<sign-in></sign-in>'
});
});
signIn.controller.js
'use strict';
(function(){
class SignInComponent {
constructor() {
this.message = 'Hello';
}
}
angular.module('orbitApp')
.component('signIn', {
templateUrl: 'app/signIn/signIn.html',
controller: SignInComponent
});
})();
I've tried a number of variations on the signIn.html script, no luck so far. I'd like to find the 'native' way to do it, so I'd rather not use jquery. Any advice would be appreciated!
I don't understand exactly what you're trying to do but I hope this code will help you :
signIn.html
<body>
<section ui-view>Response: {{response}}</section>
<a class="btn btn-info" href="#" ng-click="callingPostFct()" role="button">Trigger http post using button as example</a>
</body>
signIn.js
'use strict';
angular.module('orbitApp')
.config(function ($stateProvider) {
$stateProvider
.state('signIn', {
url: '/signIn',
template: '<sign-in></sign-in>'
});
});
signIn.controller.js
'use strict';
(function(){
class SignInComponent {
constructor($scope, $http) {
$scope.callingPostFct = function() {
$http.post('/api/auth/signin', {
//do anything you want with your api endpoint here :
auth_token: '5'
}).success(function(response) {
console.log('post successfully worked !');
$scope.response = response;
});
};
}
}
angular.module('orbitApp')
.component('signIn', {
templateUrl: 'app/signIn/signIn.html',
controller: SignInComponent
});
})();
Note :
Don't put ng-controller="" in your html files because they are already called by the generator and they will be called twice or even more which could produce some trouble in your app and reduce performance also.
In most of case, when you're trying to use <script> tag, you can do it in the controller.
I'm trying to learn how to use resolves with UI-Router, and I think there's a piece of information I'm missing, because I can't figure out how to make them work.
I have a state set like this:
app.config(['$stateProvider', function($stateProvider) {
$stateProvider
.state('testState', {
url: '/testRoute',
controller: 'TestContoller',
views: {
"body": {
templateUrl: "testHtml.html"
}
},
resolve: {
test: function(){
return {value: "test"};
}
}
})
}]);
And then I have a controller:
app.controller("TestController", ["$scope", "test", function($scope, test) {
console.log(test);
}]);
then I have a testHtml.html partial file that doesn't have anything in at the moment:
<div ng-controller="TestController">
Test content
</div>
And that gets loaded into the ui-view in index.html:
<div ui-view="body" autoscroll></div>
I've been fiddling around with this for an hour or so now and googling around and I can't quite figure out what I should be doing to get the resolve to do something and pass the result into the controller.
When you mention views properties on state level options, it ignores templateUrl & controller on that state. It only take controller & template/templateUrl from one of view.
Code
views: {
"body": {
templateUrl: "testHtml.html",
controller: 'TestContoller' //moved it to named-view level
}
},