I'm trying to populate an ion-content container. I want to load HTML into the $scope depending on which tab the user clicks:
<ion-tabs tabs-type="tabs-icon-only">
<ion-tab ...>
<ion-tab title="Create" icon-on="ion-android-create">
<ion-content padding="true" class="has-header">
{{getCreate}}
</ion-content>
</ion-tab>
<ion-tab ...>
</ion-tabs>
This is the controller for this view:
(function () {
'use strict';
angular.module('ionicApp')
.controller('HomePageController', ['$scope', '$state', '$templateCache', HomePageController]);
function HomePageController($scope, $state, $templateCache) {
$scope.getCreate = function() {
// at the moment create.html is just simple static html.
return $templateCache.get('app/views/home/ads/create.html');
//return $templateCache.get('main.create'); // this also doesn't work
};
}
})
();
The two relevant states are defined as:
.state('main.home', {
url: '/home',
views: {
'main': {
templateUrl: 'app/views/home/home.html',
controller: 'HomePageController'
}
}
})
.state('main.create', {
url: '/create',
views: {
'main': {
templateUrl: 'app/views/home/ads/create.html',
controller: 'CreateAdController'
}
}
})
Am I going about this incorrectly? What do I need to do to load create.html into $scope.getCreate in my HomePageController?
your approach seems a bit too complicated to me.
first of all you would have to make sure that your template has been loaded to $templateCache. this only happens when the template is rendered for the first time somewhere in the app (for example by using the "templateUrl" property)
alternatively you could fetch the data from the file by an ajax call on your own and compile it with the given $interpolate, $compile functions from angular. but then again: this seems way too complicated for this case.
secondly you would have to use ng-bind-html instead, because the way you did it there would be sanitized html to be seen. so there would be stuff like
etc instead of a compiled html version of it.
probably you should simply use the ng-include directive instead and everything will be fine in a blink of an eye ;)
As raised by #Patrick Kelleter, your approach is overly complex including working manually with the $templateCache and compiling HTML.
Why not use the router the way it's designed?
First, rename the state's view so that you can reference it explicitly:
.state('main.create', {
url: '/create',
views: {
'create': {
templateUrl: 'app/views/home/ads/create.html',
controller: 'CreateAdController'
}
}
})
Then change state using ui-sref= on the tab, and insert the state's template using <ion-nav-view ...> with the specially named view.
<ion-tabs tabs-type="tabs-icon-only">
<ion-tab ...>
<ion-tab title="Create" icon-on="ion-android-create" ui-sref="main.create">
<ion-content padding="true" class="has-header">
<ion-nav-view name="create"></ion-nav-view>
</ion-content>
</ion-tab>
<ion-tab ...>
</ion-tabs>
The router will then insert the content of app/views/home/ads/create.html into the <ion-nav-view name="create"> element when the tab is clicked.
Here is a full walkthrough: Build an App with Navigation and Routing - Part 1
Simply use $http.get:
$http.get($scope.template.url).then (function(response) {
console.log(response);
$scope.contents = response.data;
});
The DEMO on PLNKR.
The browser's Same Origin Policy and Cross-Origin Resource Sharing (CORS) policy may restrict whether the template is successfully loaded.
Related
Below is my controller code,
app.controller('logoutCtrl', ['$scope', '$http','$window','$state',
function ($scope, $http,$window,$state) {
$scope.logout = function() {
console.log('inside logmeout');
delete $window.sessionStorage.token;
$state.go('access.login');
};
}]);
HTML
<li class="last" ng-controller="logoutCtrl">
<a href="" ng-click="logout()">
<i class="material-icons">lock</i> Logout
</a>
</li>
app.router.js
.state('access', {
url: '/access',
template: '<div ui-view class=""></div>'
})
.state('access.login', {
url: '/login',
templateUrl: 'partials/ui-login.html',
controller: 'LoginFormController',
resolve: {
deps: ['uiLoad',
function(uiLoad) {
return uiLoad.load(['scripts/controllers/login.js',
'../bower_components/font-awesome/css/font-awesome.css']);
}
]
}
})
When clicking the logout i am not able to redirect to another state('access.login').
The control is coming inside the logout() and able to print the console message and is deleting the token as well but redirect not happening..
Can i get any help..
In your module definition you need to pass 'ui.router' as a dependency in order to use the Angular-UI-Router in your project:
E.g. angular.module('my_app', ['ionic', 'ui.router'])
It works for me as well.
$state.go('the-state-name-in-quotes')
If your web page is displayed within a view, don't forget to include ui-view in the parent page where you want to display the web page.
<div ui-view>
<!-- Child page will appear here -->
</div>
My abstract state is a frame with tabs that loads in the lower section a template depending on the active tab. The layout is similar to this:
The problem is that when I navigate back it also navigates through the tabs, instead of going to the previous state. How can I prevent this behaviour?
This is the template of my parent state
<ion-tabs>
<ion-tab ui-sref="home.user.details">
</ion-tab>
<ion-tab ui-sref="home.user.followers">
</ion-tab>
</ion-tabs>
<ion-nav-view class="inner-view"></ion-nav-view>
And this is my ui-router configuration
.state('home.user', {
url: '/user/:id',
abstract: false,
cache: true,
template: '<user></user>',
resolve: {
id: function($stateParams) {
return $stateParams.id;
}
}
})
.state('home.user.details', {
url: '/details',
templateUrl: 'template/user.details.html'
})
.state('home.user.followers', {
url: '/followers',
templateUrl: 'template/user.followers.html'
})
If you want to do this when the hardware backbutton is used you could do it with Ionic's onHardwareBackButton feature by manually setting the state where it should navigate to like this:
$ionicPlatform.onHardwareBackButton(onBackButton);
function onBackButton(e) {
$state.go('home.user');
}
You can register the above on the tab states and then remove it with offHardwareBackButton when the wanted behaviour changes like this:
$ionicPlatform.offHardwareBackButton(onBackButton);
I didn't see a back button but if you do have/want one replace it with a self made on and make it go to the parent state with something like this:
HTML:
<button class="button" ng-click="goToHome()">
<i class="icon ion-android-arrow-back"></i>
</button>
Controller:
$scope.goToHome = function() {
$state.go('home.user');
};
This could be a misunderstanding of how Angular controllers work, but I am trying to understand why the badge values for my tabs are not being updated.
I have isolated the issue to a Codepen here: https://codepen.io/tyman7/pen/JKKEbO
Extract from HTML:
<ion-tab title="Home" icon="ion-home" href="#/tab/home" badge="badgeValue" ng-controller="HomeTabCtrl">
<ion-nav-view name="home-tab"></ion-nav-view>
</ion-tab>
Extract from JS:
.controller('HomeTabCtrl', function($scope)
{
$scope.badgeValue = 1;
$scope.updateTabValue = function()
{
$scope.badgeValue += 1;
}
}
I ended up finding a solution that involves creating another controller that the badge value looks at. I have modified the isolated Codepen slighty to demonstrate: https://codepen.io/tyman7/pen/pbbRpb
Extract from HTML:
<ion-tab title="Home" icon="ion-home" href="#/tab/home" badge="badgeValue" ng-controller="HomeCtrl">
<ion-nav-view name="home-tab"></ion-nav-view>
</ion-tab>
Extract from JS:
.controller('HomeTabCtrl', function($scope)
{
})
.controller('HomeCtrl', function($scope)
{
$scope.badgeValue = 1;
$scope.updateTabValue = function()
{
$scope.badgeValue += 1;
}
}
The thing is, I just don't understand why it needs to be done this way. What fundamental knowledge am I missing here?
You had multiple instances of the HomeTabCtrl. It created one when the 'tabs' state was entered and another when the 'tabs.home' state was entered. Your 'tab' badgeValue was in one instance and the 'tabs.home' value another. An Easy fix to the original is to change the name of the 'tabs.home' controller to 'HomeCtrl' instead and create an empty controller of that name. Then the updateTabValue will be called in the parent scope and update the badgeValue throughout.
Here is a codepen:
http://codepen.io/stich12/pen/Nrrprd
I'm developing my first application. It have worked really good, but now I'm stuck with an issue related to $stateParams.
I'm developing an app which requires login and logout. And have a url in this format:
'#/tab/profile/{{userId}}'
I have a tab to show the user profile. It should read the ID from the url, and render this user.
If I login with an user, the profile is rendered correctly. But when I log out and then log in with other user, It still shows the first user profile. The $stateProvider variable, it still have the previous value.
I recorded this short video to explain my problem.
https://youtu.be/d4U1j3gKKt4
And below is my source code.
This is really driving me crazy. What should I do? Thanks a lot!
$stateProvider
// setup an abstract state for the tabs directive
.state('tab', {
url: '/tab',
abstract: true,
templateUrl: 'templates/tabs.html'
})
.state('tab.profile', {
url: '/profile/:userIdInUrl',
views: {
'tab-profile': {
templateUrl: 'templates/tab-profile.html',
controller: 'ProfileCtrl'
}
}
})
This is the tabs code. As showed in the video, the value is correctly updated:
<!-- Profile Tab -->
<ion-tab title="Profile" icon-off="ion-ios-person-outline" icon-on="ion-person" href="#/tab/profile/{{userId}}">
<ion-nav-view name="tab-profile"></ion-nav-view>
</ion-tab>
And this is my 'ProfileCtrl' code:
.controller('ProfileCtrl', function($http, $scope, $stateParams) {
$scope.$on('$ionicView.enter', function(e) {
console.log('$stateParams:');
console.log($stateParams);
});
I finally solved it. I finally managed to solve it.
I added this method:
$scope.goToUserProfile = function(){
$state.go('tab.profile', { userIdInUrl: AuthService.userId() });
};
And changed my tabs code to this:
<!-- Profile Tab -->
<ion-tab title="Profile" icon-off="ion-ios-person-outline" icon-on="ion-person" ng-click="goToUserProfile()">
<ion-nav-view name="tab-profile"></ion-nav-view>
</ion-tab>
Have a nice week!
I'm new to Ionic but it's been a long time since I wanted to try it. I'm just playing around so maybe I'm not getting the full concept.
I'm trying to do a simple application with three tabs at the bottom and a settings icon that will be there for all three tabs. When you click into that icon, supposedly the tabs should hide and show the settings screen.
Since I don't want the user to loose any content, all the views inherit from a global one:
angular.module('app', ['ionic', 'debug']).config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('app', {
url: "/app",
abstract: true,
controller: 'AppController',
templateUrl: "ui/modules/tabs/view.html"
})
.state('app.compose-text', {
url: '/text',
views: {
'compose-text': {
templateUrl: 'ui/modules/text-composer/view.html'
}
}
})
.state('app.compose-draw', {
url: '/draw',
views: {
'compose-draw': {
templateUrl: 'ui/modules/draw-composer/view.html'
}
}
})
.state('app.compose-photo', {
url: '/photo',
views: {
'compose-photo': {
templateUrl: 'ui/modules/photo-composer/view.html'
}
}
})
.state('app.settings', {
url: '/settings',
views: {
'settings': {
controller: 'ui/modules/settings/ctrl.js',
templateUrl: 'ui/modules/settings/view.html'
}
}
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/app/text');
});
angular.module('app').run(function($rootScope) {
});
Then, tabs/view looks like this:
<ion-nav-view name="settings"></ion-nav-view>
<ion-tabs class="tabs-assertive tabs-icon-only">
<ion-tab title="Text" icon="icon ion-ios7-compose-outline" href="#/app/text">
<ion-nav-view name="compose-text"></ion-nav-view>
</ion-tab>
<ion-tab title="Draw" icon="icon ion-edit" href="#/app/draw">
<ion-nav-view name="compose-draw"></ion-nav-view>
</ion-tab>
<ion-tab title="Photo" icon="icon ion-ios7-camera-outline" href="#/app/photo">
<ion-nav-view name="compose-photo"></ion-nav-view>
</ion-tab>
</ion-tabs>
And one of the views:
<ion-view title="Example" class="slide-left-right">
<ion-nav-buttons side="left">
<a class="button button-icon button-clear ion-ios7-gear-outline" href="#/app/settings"></a>
</ion-nav-buttons>
<ion-content padding="true">
<h1>Text</h1>
</ion-content>
</ion-view>
First thing I wonder is: Is there any way to reuse those buttons between all views? Seems useless to keep defining them over and over.
But that's not the real thing™. When I click on Settings, something get injected into the ion-nav-view however it contains a lot of stuff (which is not on the template) and also, it doesn't hide the other view nor the tabs.
Some screenshot:
(source: ionicframework.com)
What should be the right approach for this?
This is my first time answering a question here so please bear with me.
To navigate to a view without the tab bar:
Remove the "app" prefix from the settings state, so it is no longer a child to the parent abstract state (app).
.state('settings', {
url: '/settings',
views: {
'settings': {
controller: 'ui/modules/settings/ctrl.js',
templateUrl: 'ui/modules/settings/view.html'
}
}
});
**If you add any states after this one, be sure to delete semicolon, whereas semicolon denotes the end.
THAT IS A BAND-AID SOLUTION.
The full solution to your problem is to start with an ionic project template. Fortunately they have a tabs option, which is a global tab bar.
Command-line:
ionic start appName tabs
That should give you a proper starting template with everything you need. It also has sample controllers.js, services.js, and app.js files so you can just build from there. It will also help you structure your project correctly to prevent unexpected data from injecting into your tag.
Source 1: http://ionicframework.com/getting-started/
Source 2: http://ionicframework.com/docs/api/directive/ionNavView/
**Bonus: There is also a neat trick in source 2 that shows you how to keep all templates inside your index.html file to speed up the app and simplify your workflow.
Goodluck.