AngularJS - (using Ionic framework) - data binding on header title not working - angularjs

I'm using an AngularJS-based library called "Ionic" (http://ionicframework.com/).
This seems simple, but it isn't working for me.
In one of my views, I have the following
<view title="content.title">
<content has-header="true" padding="true">
<p>{{ content.description }}</p>
<p><a class="button button-small icon ion-arrow-left-b" href="#/tab/pets"> Back to home</a></p>
</content>
</view>
In the controller for the above view, I have
angular.module('App', []).controller('DetailCtrl', function($scope, $stateParams, MyService) {
MyService.get($stateParams.petId).then(function(content) {
$scope.content = content[0];
console.log($scope.content.title); // this works!
});
});
The data for this view is loaded via a simple HTTP GET service (called MyService).
The problem is that when I view this page,
<view title="content.title">
Doesn't display the title. It's just a blank. According to the Ionic documentation (http://ionicframework.com/docs/angularjs/controllers/view-state/), I think I'm doing the right thing.
It's strange that {{content.description}} part works, but content.title doesn't work?
Also, is it because I'm loading the content dynamically (via HTTP GET)?

By using the ion-nav-title directive (available since Ionic beta 14), the binding seems to work correctly.
Rather than
<ion-view title="{{content.title}}">
....
Do this
<ion-view>
<ion-nav-title>{{content.title}}</ion-nav-title>
...
Works a treat.

A solution for newer versions of Ionic is to use the <ion-nav-title> element rather than the view-title property. Just bind your dynamic title inside the content of the <ion-nav-title> using curly brace syntax. Example:
<ion-view>
<ion-nav-title>
{{myViewTitle}}
</ion-nav-title>
<ion-content>
<!-- content -->
</ion-content>
</ion-view>

Here's a working example of how to accomplish this in Ionic. Open the menu, then click "About". When the "About" page transitions, you will see the title that was resolved.
As Florian noted, you need to use a service and resolve to get the desired effect. You then inject the returned result into the controller. There are some down sides to this. The state provider will not change the route until the promise is resolved. This means there may be a noticeable lag in the time the user tries to change location and the time it actually occurs.
http://plnkr.co/edit/p9b6SWZmBKWYm0FIKsXY?p=preview

If you look at ionic view directive source on github, it's not watching on title attributes which means it won't update your view when you set a new value.
The directive is processed before you receive the answer from server and you fill $scope.content.title.
You should indeed use a promise in your service and call it in a resolver. That or submit a pull request to ionic.

I was encountering the same problem and was able to solve it by wrapping my title in double-curlies.
<ion-view title="{{ page.title }}">
I should note that my page.title is being set statically by my controller rather than from a promise.

I had a very similar issue where the title wouldn't update until i switched pages a couple of times. If i bound the title another place inside the page, it would update right away. I finally found in the ionic docs that parts of those pages are cached. This is described here http://ionicframework.com/docs/api/directive/ionNavView/
To solve my issue, I turned caching off for the view with the dynamic title:
<ion-view cache-view="false" view-title="{{title}}">
...
</ion-view>

I got this to work on older versions of Ionic using the <ion-view title={{myTitle}}> solution (as per plong0's answer).
I had to change to <ion-view view-title= in the more recent versions. However using beta-14 it's showing blank titles again.
The nearest I've got to a solution is to use $ionicNavBarDelegate.title(myTitle) directly from the controller. When I run this it shows the title briefly and a moment later blanks it.
Very frustrating.

It's the first time that I worked with dynamic title in Ionic 1.7 and I run into this problem. So I solved using $ionicNavBarDelegate.title(') from the controller, as mentioned Kevin Gurden. But additionally, I used cache-view="false".
View:
<ion-view cache-view="false"></ion-view>
Controller:
angular
.module('app', [])
.controller('DemoCtrl', DemoCtrl);
DemoCtrl.$inject = ['$ionicNavBarDelegate'];
function DemoCtrl($ionicNavBarDelegate) {
$ionicNavBarDelegate.title('Demo View');
}

Use ion-nav-title instead of the directive view-title.
see http://ionicframework.com/docs/api/directive/ionNavTitle/

This is the true solution: data bind the ion-nav-title directive
<ion-view>
<ion-nav-title ng-bind="content.title"></ion-nav-title>
<ion-content has-header="true" padding="true">
<p>{{ content.description }}</p>
<p><a class="button button-small icon ion-arrow-left-b" href="#/tab/pets"> Back to home</a></p>
</ion-content>
</ion-view>
http://ionicframework.com/docs/api/directive/ionNavTitle/

I m using ionic v1.3.3 with side menus based template. I tried all solutions given above but no luck.
I used the delegate from $ionicNavBarDelegate:
http://ionicframework.com/docs/v1/api/service/$ionicNavBarDelegate/
I created a function inside my angular controller to set the title :
angular.module('app.controllers').controller('contributionsCtrl', contributionsCtrl);
function contributionsCtrl($scope, $ionicNavBarDelegate) {
vm.setNavTitle = setNavTitle;
function setNavTitle() {
var title = "<span class='smc_color'> <i class='icon ion-images'></i> Your Title </span>"
$ionicNavBarDelegate.title(title);
}
}
Then inside my html just called the function vm.setNavTitle
<ion-view overflow-scroll=true ng-init="vm.setNavTitle()">
<ion-content></ion-content>
</ion-view>

<ion-view> <ion-nav-title>{{ result.title }}</ion-nav-title>
This work for me

Related

How to access DOM element outside of ion-content view

Running an Ionic v1 app, in my template page I have:
<ion-view>
<ion-nav-title>
<div id="navTitle"></div>
</ion-nav-title>
<ion-content>
</ion-content>
</ion-view>
From the view controller, I am trying to get the div element with: var el = document.getElementById("navTitle"); but its errors indicating the el is null. It seems ionic can't see elements outside of the ion-content
How can I get the element?
I figured it out. Turns out I needed to add a slight delay to a function that was being called when the controller was entered. The function was trying to access the dom element before it was set in the ion-nav-title section.
setTimeout(function() {
doFunction() ;
},500) ;
Its not ideal, but it did the trick
UPDATE:
I found a better way. Elements outside of the ion-content should be assigned an ng-model, and then the model can be accessed from the normal scope:
<div id="navTitle" ng-model="$parent.navTitle"></div>
<ion-content>
...
</ion-content>
Then in the controller, it can accessed with $scope.navTitle

Ionic - How to use two controllers conditionally in one modal

I am working on ionic project, where I need to use single modal view & conditionally call controller for it.
I am trying to do like following -
<div ng-if="!isEditMode" ng-controller="Controller1">
<div ng-if="isEditMode" ng-controller="Controller2">
<ion-content>
<!-- My view code -->
</ion-content>
</div>
</div>
here, both controller are get called(can see console in controller). but html page not get rendered just white screen appear.
If I remove controller2 then it works fine with just one controller.

Render directive in html string with AngularJS

I am trying to render a directive and have it properly displayed in HTML with AngularJS. I have a service that takes care of displaying warning messages to the users. Per controller I can call this service and set a message I want to be displayed. Now one of those messages is supposed to include a link. However as I am using the Ionic framework I need to use a directive to accomplish exactly that.
HTML:
<div class="bar bar-loading bar-assertive top-bar">
| {{ message }}
</div>
JS:
$scope.message = "Please visit this link: <a ui-sref='app.settings.profile-show'>Open me.</a>"
However the message is not properly output in the html. If I use the following I get the html, but the directive is not evaluated:
<div class="bar bar-loading bar-assertive top-bar" ng-bind-html="message"></div>
How would I accomplish something like this? Thank you.
I am not sure about Ionic framework, But this is my way to render HTML content. Use $sce.trustAsHtml(html) to render text as html. Your code will look something like this.
// ...
app.controller('yourCtrl', function ($scope,$sce) {
$scope.message = "Please visit this link: <a ui sref='app.settings.profile-show'>Open me.</a>";
$scope.renderHTML = function(html_code){
return $sce.trustAsHtml(html_code);
};
}
html
<div class="bar bar-loading bar-assertive top-bar" ng-bind-html="renderHTML(message)"></div>
<!-- or this way? -->
<div class="bar bar-loading bar-assertive top-bar">
| {{ renderHTML(message) }}
</div>
<!-- not sure about second option, but either should work -->
Hope it helped!

Master Page Concept in AngularJS?

I would like to create master page, that is main page which will be used in all views of the application.
For example, Left navigation and top men navigation. This navigation should be displayed in all the views, whenever url changes in application.
As per ng-view, it only renders given partial view and replace previous view. In the image above all my left and top navigation should be displayed by using angular Controller.
Controller code
angular.module('modelDemo').controller("authCtrl", ['$scope', function($scope) {
$scope.list;
}]);
Please let me know, how can i achieve this
You can use angular-route or Angular-ui-router, and setting your master, following this steps:
Step 1. Make your index.html your master page.
Step 2. Add the <header>, <footer>, <aside>, <div>, etc. referencing your templates by using ng-include
NOTE: your left and top navigation will be part of it
Step 3. The content of the view will be rendered using the directive attribute ng-view or ui-view
Step 4. Use your module app.config() to configure the children pages
Source:
using Angular Route: https://docs.angularjs.org/tutorial/step_07
template for a brand-new app: https://github.com/angular/angular-seed
using Angular UI Router: Angular Tutorial 30 mins
ng view should be able to do that just fine. Keep your top navigation / left navigation html intact and use ng view for the various display area. http://docs.angularjs.org/api/ng.directive:ngView
To use the controller from the top navigation inside ng-view you can use $parent to get access to that scope : https://stackoverflow.com/a/14700326/390330
Fiddle for parent scope : http://jsfiddle.net/ezhrw/2/
<button ng:click="$parent.letter = greek">Assignment expression {{ greek }}</button>
I was trying to create the same concept, but needed a way to define placeholders. I started experimenting in Plnkr.co and thus far, I resorted to using a LayoutManager that drives itself from settings within the routeProvider object.
Here is an example: http://embed.plnkr.co/4GPDfTSQCuqukJE7AniZ/
You'll see an example of how multiple routes use the same header and footer, I did not include an example with a sidebar.
Let me explain the LayoutManager.
I wanted to have placeholders that could be overridden. In this example, I have a toolbar that contains a title and provides a space to the right of the title for additional toolbar items. This gives views an opportunity to throw in additional functionality.
All of this is driven by the LayoutManager. The LayoutManager is a service that reads layout properties set on the $routeProvider. I wanted to implement this in a way keep things clean and self contained, per route. The LayoutManager is injected into the toolbar directive. The toolbar directive drives it's scope properties of the LayoutManager.
In turn, the LayoutManager has a dependency on the routeProvider as well as the rootScope $routeChange event.
I'm very new to Angular, open to suggestions.
I could not see any problem, if you are using bootstrap then use can easily divide your screen as you want
<div class="row">
<div class="col-lg-3">
Left panel
</div>
<div class="col-lg-9" style="border:1px solid #999; overflow-y:auto">
<div> Top Banner </div>
<!-- Main view to render all the page -->
<div ui-view> </div>
</div>
</div>
If you want complete demo and code on then see this link
Edited: 3 Nov. 2016:
If you are using ui-router then we can user abstract state to create different master pages.
You don't need to play show/hide, ng-if but just define the routing properly with you master pages and child pages
Better to see the detail
I know this is an old thread, but thought it should be noted that as of Angular 1.5+ we have been introduced to components. Instead of dealing with routes with named views and all that nonsense or using ngInclude you should be using a header component and footer component. Simply add these to your index.html (or whatever you call your master html template) and voila.
For example (this is using Angular Material and is missing the layout module but hopefully you get the point)
1. Added to index.html
<layout-header></layout-header>
2. header.component.js (you don't need all of this but I think it's helpful)
(function () {
'use strict';
angular
.module('layout')
.component('layoutHeader', {
templateUrl: 'layout/header.html',
bindings: {},
controller: Controller
});
Controller.$inject = [];
function Controller() {
var ctrl = this;
initialize();
////////////////////
function initialize(){
}
}
}());
3. header.html
<md-toolbar>
<div class="md-toolbar-tools">
<h2>
<span>Really Awesome Title!!!!</span>
</h2>
<span flex></span>
<md-button class="md-icon-button" aria-label="More">
<md-icon class="material-icons">more_vert</md-icon>
</md-button>
</div>
</md-toolbar>

How to open an angularjs page as a popup from another angularjs page

I have 2 CakePHP pages. Both of them use angularjs. Here's a snippet.
/items/items.ctp
<div id="ng-app" ng-app>`
<div ng-controller="ItemController">
Add
</div>
</div>
the function showAddPopup is defined as follows
$scope.showAddPopup = function() {
$.colorbox({href:'/items/add/' + $scope.order.id,open:true,close : "x", onClosed:function(){}});
}
/items/add.ctp
<div id="ng-app" ng-app>`
<div ng-controller="AddController">
<h2>{{order.label}}<h2>
</div>
</div>
Now, when I click on the add link from items view, I get a popup with the contents of add.ctp. But the problem is that instead of showing order label say 'My Order', the h2 tag is showing {{order.label}}
When I open add view from a page that doesn't use angularjs I get a proper result. What am I doing wrong. Please help. I have already wasted many days on this.
Maybe opening the colorbox with setting iframe could be the solution, if the problem is nested ng-apps.
$.colorbox({inline:false; iframe:true;href:'/items/add/'...});
If you are using bootstrap then angular-ui would be a great choice for above scenario

Resources