I am updating angular 1.6 based web application from 'controller-based' to 'component-based app'.
Here is my code snippet:
dashboard-component.js
angular.module('app').component('dashboardComponent' , {
template: '<a>Hello</a>',
controller: function dashboardController() {
var vm = this;
console.log("dashboardController loaded");
}
}
And app-router.js:
angular.module('app').config(function($stateProvider, $urlRouterProvider){
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'framework/src/layout/template.html',
data: {
BreadCrumbLabel: 'Home'
}
})
.state('app.dashboard', {
url: '/dashboard',
component: 'dashboardComponent',
/* templateUrl: 'app/components/pages/dashboard/dashboard.html',
controller: 'dashboardCtrl',
controllerAs: 'dashboardCtrl',*/
})
});
I'd included them in index.html properly:
<script src="app/app.router.js"></script>
<script src="app/components/pages/dashboard/dashboard.component.js"></script>
If I remove the comment in the app.router.js file and recover routing by 'dashboardController', it works correctly, but it doesn't work if I set routing entry to 'component'.
This is just a simple sample, and it seems component is not loaded, even console.log is not working.
Here is a plunkr link: https://plnkr.co/edit/1aZ2aahTfT4AHIraWPCt?p=preview
Is this something you faced before? Would you like to help me?
Related
When I view the page in Google Chrome and I click on the goal list that has been generated the URL changes to URL/#/tabs/personalview but the view fails to change.
This is the code in my personalGoals.html file:
<ion-view view-title="PersonalGoals">
<ion-content class="has-footer">
<ion-item ng-repeat="goal in goals" href="#/tabs/personalview">
<span class="goal-lists">{{goal.goaltitle}}</span>
</ion-item>
</ion-content>
</ion-view>
This is the code in my app.js file:
.config(function($stateProvider, $urlRouterProvider, $ionicConfigProvider) {
$ionicConfigProvider.tabs.position('bottom');
$stateProvider
.state('tabs', {
url: '/tabs',
abstract: true,
templateUrl: 'templates/tabs.html'
})
.state('tabs.personal', {
url: '/personal',
views: {
'personalGoals-view': {
templateUrl: 'templates/personalGoals.html',
controller: 'personalCtrl'
}
}
})
.state('tabs.personalview', {
url: '/personalview',
templateURL: 'templates/test.html',
controller: 'personalViewCtrl'
})
.state('tabs.relationship', {
url: '/relationship',
views: {
'relationshipGoals-view': {
templateUrl: 'templates/relationshipGoals.html',
controller: 'relationshipCtrl'
}
}
})
.state('tabs.squad', {
url: '/squad',
views: {
'squadGoals-view': {
templateUrl: 'templates/squadGoals.html',
controller: 'squadCtrl'
}
}
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('tabs/dashboard');
});
You can see the full code over here.
Any help would be greatly appreciated, thank you in advance.
I think your problem is that you're trying to navigate to the wrong URL.
You are trying to navigate to the state name when you should be navigating to the state URL.
There are two ways to do this:
You can continue to use href, and change the URL to #/personalview
You can use ui-sref instead of href and do something like ui-sref="tabs.personalview"
You might check out the following for reference:
https://www.thepolyglotdeveloper.com/2014/11/using-ui-router-navigate-ionicframework/
https://www.thepolyglotdeveloper.com/2014/12/using-nested-states-angularjs-ui-router/
Best,
I want to give 2 parts of my UI the same controller but still let them have each of their own unique controllers.
$stateProvider
.state('standard.page', {
url: '/:page',
resolve: {
page: function($stateParams) {
...
},
},
views: {
'content': {
templateUrl: '/tmpl/page',
controller: 'controllercontent'
},
'sideMenu': {
templateUrl: '/tmpl/menu',
controller: 'controllermenu',
}
}
})
So I want both content and sideMenu to share a controller. If I add a controller above the views then it requires a new template, I want to use the standard template instead of making a unique template for this state. Any ideas how I can get 3 controllers going in this example? Thanks.
I battled with this at some point in time, and I believe I made a template file that isn't directly accessible (via abstract: true). Here's an example...
.state('standard', {
url: '/standard',
abstract: true,
templateUrl: '/tmpl/standard.html',
controller: 'SharedController'
},
})
.state('standard.page', {
url: '/:page',
resolve: {
page: function($stateParams) {
...
},
},
views: {
'content': {
templateUrl: '/tmpl/page',
controller: 'controllercontent'
},
'sideMenu': {
templateUrl: '/tmpl/menu',
controller: 'controllermenu',
}
}
});
In your tmpl/standard.html file, make sure this exists somewhere within the file:
<div ui-view="sideMenu">
<div ui-view="content">
Hope this points you in the right direction.
I am trying to do what was essentially answered here Unable to open bootstrap modal window as a route
Yet my solution just will not work. I get an error
Error: [$injector:unpr] Unknown provider: $modalProvider <- $modal
My app has the ui.bootstrap module injected - here is my application config
var app = angular.module('app', ['ui.router', 'ui.bootstrap','ui.bootstrap.tpls', 'app.filters', 'app.services', 'app.directives', 'app.controllers'])
// Gets executed during the provider registrations and configuration phase. Only providers and constants can be
// injected here. This is to prevent accidental instantiation of services before they have been fully configured.
.config(['$stateProvider', '$locationProvider', function ($stateProvider, $locationProvider) {
// UI States, URL Routing & Mapping. For more info see: https://github.com/angular-ui/ui-router
// ------------------------------------------------------------------------------------------------------------
$stateProvider
.state('home', {
url: '/',
templateUrl: '/views/index',
controller: 'HomeCtrl'
})
.state('transactions', {
url: '/transactions',
templateUrl: '/views/transactions',
controller: 'TransactionsCtrl'
})
.state('login', {
url: "/login",
templateUrl: '/views/login',
controller: 'LoginCtrl'
})
.state('otherwise', {
url: '*path',
templateUrl: '/views/404',
controller: 'Error404Ctrl'
});
$locationProvider.html5Mode(true);
}])
I have reduced my controller to the following:
appControllers.controller('LoginCtrl', ['$scope', '$modal', function($scope, $modal) {
$modal.open({templateUrl:'modal.html'});
}]);
Ultimately, what I am hoping to achieve is when login is required not actually GO to the login page, but bring up a dialog.
I have also tried using the onEnter function in the ui-router state method. Couldn't get this working either.
Any ideas?
UPDATE
Ok - so as it turns out, having both ui-bootstrap.js AND ui-bootstrap-tpls breaks this - After reading the docs I thought you needed the templates to work WITH the ui-bootstrap. though it seems all the plunkers only load in the ..tpls file - once I removed the ui-bootstrap file my modal works...Am i blind? or doesn't it not really say which one you need in the docs on github? -
Now i just need to figure out how to prevent my url from actually going to /login, rather than just show the modal :)
update 2
Ok, so by calling $state.go('login') in a service does this for me.
Hi I had a hard time getting through the similar problem.
However, I was able to resolve it.
This is what you would probably need.
app.config(function($stateProvider) {
$stateProvider.state("managerState", {
url: "/ManagerRecord",
controller: "myController",
templateUrl: 'index.html'
})
.state("employeeState", {
url: "empRecords",
parent: "managerState",
params: {
empId: 0
},
onEnter: [
"$modal",
function($modal) {
$modal.open({
controller: "EmpDetailsController",
controllerAs: "empDetails",
templateUrl: 'empDetails.html',
size: 'sm'
}).result.finally(function() {
$stateProvider.go('^');
});
}
]
});
});
Click here for plunker. Hope it helps.
I'm working on something similar and this is my solution.
HTML code
<a ui-sref="home.modal({path: 'login'})" class="btn btn-default" ng-click="openModal()">Login</a>
State configuration
$stateProvider
// assuming we want to open the modal on home page
.state('home', {
url: '/',
templateUrl: '/views/index',
controller: 'HomeCtrl'
})
// create a nested state
.state('home.modal', {
url: ':path/'
});
Home controller
//... other code
$scope.openModal = function(){
$modal.open({
templateUrl: 'path/to/page.html',
resolve: {
newPath: function(){
return 'home'
},
oldPath: function(){
return 'home.modal'
}
},
controller: 'ModalInstanceController'
});
};
//... other code
Finally, the modal instance controller.
This controller synchronizes the modal events (open/close) with URL path changes.
angular.module("app").controller('ModalInstanceController', function($scope, $modalInstance, $state, newPath, oldPath) {
$modalInstance.opened.then(function(){
$state.go(newPath);
});
$modalInstance.result.then(null,function(){
$state.go(oldPath);
});
$scope.$on('$stateChangeSuccess', function () {
if($state.current.name != newPath){
$modalInstance.dismiss('cancel')
}
});
});
You may create a state with the same templateUrl and controller as your page where you want to show the modal, adding params object to it
$stateProvider
.state('root.start-page', {
url: '/',
templateUrl: 'App/src/pages/start-page/start-page.html',
controller: 'StartPageCtrl'
})
.state('root.login', {
url: '/login',
templateUrl: 'App/src/pages/start-page/start-page.html',
controller: 'StartPageCtrl',
params: {
openLoginModal: true
}
})
And in controller of the page, use this parameter to open the modal
.controller("StartPageCtrl", function($scope, $stateParams) {
if ($stateParams.openLoginModal) {
$scope.openLoginModal();
}
I found a handy hint to get this working. There are probably caveats, but it works for me. You can pass a result still but I have no need for one.
Using finally instead of the then promise resolve sorted this for me. I also had to store the previous state on rootScope so we knew what to go back to.
Save previous state to $rootScope
$rootScope.previousState = 'home';
$rootScope.$on('$stateChangeSuccess', function(ev, to, toParams, from, fromParams){
$rootScope.previousState = from.name;
})
State using onEnter
$stateProvider.state('contact', {
url: '/contact',
onEnter: function ($state, $modal, $rootScope){
$modal.open({
templateUrl: 'views/contact.html',
controller: 'ContactCtrl'
}).result.finally(function(){
$state.go($rootScope.previousState);
})
}
});
I have an Angular application that depends on Angular ui-router. This application has multiple pages which share a common template such as the navbar:
var app = angular.module('app', ['ngSanitize', 'ngResource', 'ngRoute', 'ui.router'])
.config(['$urlRouterProvider', '$stateProvider', ($urlRouterProvider, $stateProvider) => {
$urlRouterProvider.otherwise("/index");
$stateProvider
.state('index', {
url: "/index",
views: {
'navbar': {
templateUrl: 'Views/Partials/navbar.cshtml',
controller: 'App.Controllers.NavbarController'
},
'content': {
templateUrl: 'Views/index.cshtml',
controller: 'App.Controllers.IndexController'
}
}
})
.state('settings', {
url: "/settings",
views: {
'navbar': {
templateUrl: 'Views/Partials/navbar.cshtml',
controller: 'App.Controllers.NavbarController'
},
'content': {
templateUrl: 'Views/settings.cshtml',
controller: 'App.Controllers.SettingsController'
}
}
});
}]);
Both '/index' and '/settings' share the same template 'Views/Partials/navbar.cshtml'. Upon testing, i found out, that every time a "page" is loaded for an url, all the views in it are reloaded.
Is it possible to avoid reloading the navbar, if it has been previously loaded already?
You should be able to extract the navbar into a parent state of your existing states. This way the navbar only loads when the parent state is entered and you should be able to change child states that share this parent without affecting it.
While there are better organised ways to do this, my quick and dirty way would be to rename the states you have to withnav.index and withnav.settings. Then remove the navbar view from them and add the following state.
$stateProvider
.state('withnav', {
abstract: true,
views: {
'navbar': {
templateUrl: 'Views/Partials/navbar.cshtml',
controller: 'App.Controllers.NavbarController'
}
}
});
WikiApp.config(function config($stateProvider, $urlRouterProvider) {
$stateProvider
.state('revision', {
url: '/wiki',
views: {
"main": {
controller: 'ListCtrl',
templateUrl: 'wiki/wiki.tpl.html'
},
"sidebar-left": {
templateUrl: 'wiki/wiki.sidebar-left.tpl.html'
}
},
data:{ pageTitle: 'List articles' }
})
This is what my Angular bit looks like and this is how I execute it inside of a template (wiki.tpl.html):
<div ui-view="sidebar-left"></div>
Now the main view works fine, but as I try to integrate the sidebar, it doesn't load, what am I doing wrong and how can I use more than one template in a single page like this?
Thank you!
WikiApp.config(function config($stateProvider, $urlRouterProvider) {
$stateProvider
.state('revision', {
url: '/wiki',
views: {
main: {
controller: 'ListCtrl',
templateUrl: 'wiki/wiki.tpl.html'
},
sidebarLeft: {
templateUrl: 'wiki/wiki.sidebar-left.tpl.html'
}
},
data:{ pageTitle: 'List articles' }
})
If you want to use nested templates you should implement that using sub-views. In your current example you are setting both templates as sibling templates.
I suggest you to create 2 states. Abstract view for the main template 'main' and another view 'main.wiki'. Route should be assigned to 'main.wiki' state ant it will inherit parameters from the main view (including template settings).
Hope that's clear.