Ionic - How to use two controllers conditionally in one modal - angularjs

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.

Related

Angular JS ng-click inside a modal window / Refresh angular scope in modal callback

I'm loading a modal window into my html using magnific popup, which is essentially doing this:
<html ng-app='basket'>
<body ng-controller='BasketController as basket'>
<a id='open' href='/product/1'>Open modal</a>
<a ng-click='addToCart(1)'>Add to cart</a>
</body>
</html>
... After Ajax load
<html ng-app='basket'>
<body ng-controller='BasketController as basket'>
<div class='modal>
<h1>Product title</h1>
<a ng-click='addToCart(1)'>Add to cart</a>
</div>
<a id='open' href='/product/1'>Open modal</a>
<a ng-click='addToCart(1)'>Add to cart</a>
</body>
</html>
But the ng-click inside the modal doesn't fire. Is there a way I can refresh the scope with the modal content included?
To begin with, I thought I'd give it a go by adding an ng-click to the open modal button that can pass the scope to another function that opens the modal. I have a function that can console log the $scope after it has loaded, but I just need to refresh or something to make angular recognise the new html in the modal window.
The reason this doesn't work is because angularJS is not aware of the ng-click inside the modal. It was added by jQuery by the looks of it. AngularJS has not processed that HTMl and the ng-click does nothing.
You can, however, potentially use the $compile function in AngularJS to $compile the modal HTML with a particular scope. Then, the ng-click will work.
Have a read about $compile here:
https://docs.angularjs.org/api/ng/service/$compile
So an example in your case might be:
$compile(modalElement)($scope);
Where this happens inside BasketController, so that would be BasketController passed in to manage modalElement - the raw DOM element, not the jQuery element.
So at some point if you have access to the modal html (just after load) you could do that. Not recommended at all though! Use an Angular library.

Include kendo-window in angular js directive:Error: Multiple directives [contgoPopup, kendoWindow] asking for transclusion

I'm trying to build a directive which will display a kendo window with a kendo tab strip in its body content.
It's a component I need to be reusable since I use it a lot in my web app.
Here is the flat html representation that I want to turn into a directive
<div style="padding:20px;" kendo-window="test" id="test" k-title="hello" k-options="popupOptions">
<div kendo-tab-strip k-content-urls="[ null, null]">
<!-- tab list -->
<ul>
<li class="k-state-active">View</li>
<li>Edit</li>
</ul>
<div style="padding: 1em">
This is the view tab
</div>
<div style="padding: 1em">
This is the edit tab
</div>
</div>
</div>
1) First step is creating the directive that wraps the kendo popup and this si where I'm having an issue
So basically, my directive includes the kendo-window widget in its template and has transclude="true", since the content of the popup will different each time.
It seems "transclude" and "scope" cause some issues.
Please have a look : http://plnkr.co/edit/c7qoKlh75s8aS7fazYSo

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

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

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