Ng-click does not work first time - but works afterwards - angularjs

I have two states/views called bookmark and bookmarked.
The bookmark view has a button which passes an url into a function called setURL. This function sets the src for the iframe on the bookmarked view.
<ion-view view-title="Bookmarks">
<ion-content>
<button class="button" ui-sref="myLearning.bookmarked" ng-click="setURL('SOMEURL')">Bookmark</button>
</ion-content>
<div class="bar bar-footer bar-assertive"></div>
</ion-view>
The bookmarked view has an iframe whose src is set by the button on the previous view. The src is currently set to nothing because I would never navigate to this view unless I've clicked the bookmark button which would pass in an url.
<ion-view view-title="Bookmarked">
<ion-content>
<iframe id="learningFrame" src="" width="100%" height="100%" seamless></iframe>
</ion-content>
</ion-view>
When I run the app and navigate to the bookmark view and click on the bookmark button, it navigates to the bookmarked view but it displays a blank page in the iframe (src="") rather than using the url passed in from the function. However, from this blank page if I navigate to the bookmarks view and click on the bookmark button the second time, the actual url loads.
Why does it the view not use the url that I have passed in through setURL, on the first load?
This is what the function looks like:
.controller('bookmarkCtrl', function($scope){
$scope.setURL = function(currURL){
document.getElementById('learningFrame').src = currURL;
};
});
I don't know why it does not work the first time...
Any help would be appreciated, thank you.

Instead of doing DOM manipulation from the controller you could simply use ng-src that would have {{}} to have decide src attribute value.
Markup
<ion-view view-title="Bookmarked">
<ion-content>
<iframe id="learningFrame" ng-src="{{learningFrameUrl}}" width="100%" height="100%" seamless></iframe>
</ion-content>
</ion-view>
Controller
.controller('bookmarkCtrl', function($scope){
$scope.setURL = function(currURL){
$scope.learningFrameUrl = currURL;
};
});
Update
As you wanted to share data between you controllers then you could use service/factory component. Then you can use that service by injecting it inside your controller/directive wherever you wanted to use it.
Service
app.service('dataService', function(){
this.learningFrame = {
Url: ''
};
//..other stuff here..//
});
Controller
.controller('bookmarkCtrl', function($scope, dataService){
$scope.setURL = function(currURL){
//this can be available in other controller
//wherever you take value from learningFrameUrl
$scope.learningFrame = dataService.learningFrame;
dataService.learningFrame.Url = currURL;
};
});

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

Model change not getting reflected in view in angularjs

I have got a main index page, in which i initially hide the footer bar. But i want to display it when some item is clicked in some child view. I can see in the logs the model is getting changed, but its not getting reflected in the view.
index page:
<body ng-app="starter">
<ion-pane ng-controller="AudioCtrl">
<ion-nav-bar class="bar-positive">
<ion-nav-back-button>
</ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view></ion-nav-view>
<ion-content></ion-content>
<ion-footer-bar ng-hide="musicBar.hide">
<div class="audio-block">
.....
</div>
</ion-footer-bar>
</ion-pane>
</body>
The child view page:
<ion-view ng-controller="AudioCtrl as controller" title="{{selectedCategory}}">
<ion-content>
<ion-list>
<ion-item ng-repeat="item in items" ng-click="$parent.songClicked()">{{item.desc}}</ion-item>
</ion-list>
</ion-content>
</ion-view>
The angular code:
app.controller('AudioCtrl', function ($sce, $scope) {
$scope.musicBar= {
hide: true
};
$scope.songClicked = function(){
console.log($scope.musicBar.hide);
$scope.musicBar.hide = false;
console.log($scope.musicBar.hide);
};
}
);
When i click the item i can see musicBar.hide changing from true to false, but its not reflected in the view. I have also check other similar questions but the solution doesn't work. I have tried using $scope.$digest() and $scope.$apply(), but then i get apply already in progress.
The index.html and the cub view are each managed by their own instance of AudioCtrl, each having their own scope.
The header is made visible when the main view scope's musicBar.hide becomes true, but that never happens, because the subview doesn't modify it. It modifies the sub view scope's musicBar.hide variable.
I don't see any reason why a sub view would have the same controller as the main view. It shouldn't.

Passing data to ionic popover in ng-repeat

I want to add ionic Popover to my application and place in under ng-repeat however I am struggling a bit with this.
How can I pass a parameter to it?
<p ng-repeat="query in ctrl.timesheet">query.Name<button ng-click="openPopover($event)">Open Popover</button></p>
<script id="my-popover.html" type="text/ng-template">
<ion-popover-view>
<ion-header-bar>
<h1 class="title">My Popover Title</h1>
</ion-header-bar>
<ion-content>
<button ng-click="ctrl.delete(index)">Delete</button>
</ion-content>
</ion-popover-view>
</script>
So in short I want a list of buttons and whenever i click the popover for the button than there is a option to delete the element.
See this demo: http://play.ionic.io/app/eb32466d892c
You can pass scope of your controller to pop over, so whatever you have in parent controller will be available in pop over. Pass a parameter index in openpopover funtion : ng-click = "openPopover($event, pass-index-here)"> and bind it to $scope.index before you open popup, See this:
$ionicPopover.fromTemplateUrl('my-popover.html', {
scope: $scope
}).then(function(popover) {
$scope.popover = popover;
});
$scope.openPopover = function($event,index) {
$scope.index = {'value' : index}; //i am using object, because simple variable shows binding problem some time
$scope.popover.show($event);
};
Now this $scope.index will be available in popover, and will contain latest index of item, which you have clicked because we update its value before opening popover :
<button ng-click="ctrl.delete(index.value)">Delete</button>

Ionic side menu bar not hide properly

I have a ion menu which contain 2 links , Dashboard, favorite.
At the very first time Dashboard page is loaded for application with content. Now when i switch to another menu item. My Content seems populated first after that side menu hides. This causes user experience using the app is bad.
Can we hide side menu first then populated content.
I also tried following steps
<ion-list>
<ion-item menu-close href="#/app/articles" ng-click="toggleLeft()">
Dashboard
</ion-item>
<ion-item menu-close href="#/app/favourite" ng-click="toggleLeft()">
Favorite
</ion-item>
</ion-list>
and
$scope.toggleLeft = function() {
$ionicSideMenuDelegate.toggleLeft();
};
which also doesn't make any effect .
Here is my Dashboard page:-
<ion-view>
<ion-content>
<ion-list can-swipe="true">
<ion-item class="list article-list" ng-repeat="article in articles">
my divs
</ion-item>
</ion-list>
</ion-content>
</ion-view>
and controller is :
.controller('ArticleCtrl', function($scope, $rootScope ,articleService) {
//This is fetching data from database (**Sql lite**)
articleService.fetchArticles().then(function(articles){
$rootScope.articles = articles;
}
});
Similar code for Favorite with different controller.
Any suggestions?
Thanks
This is actually default behaviour but it can be changed. Ionic offers a few events that can be watched and you can than control when to do something. In your case I would populate the $scope only after the view fully enters the screen.
$scope.$on('$ionicView.enter', function (viewInfo, state) {
$scope.data = _getData();
});
So basically the data that you are filling the view with needs to be associated with the $scope only when the view is fully visible.
Edit:
.controller('ArticleCtrl', function($scope, $rootScope ,articleService) {
//This is fetching data from database (**Sql lite**)
var _articles;
articleService.fetchArticles().then(function(articles){
_articles = articles;
}
$scope.$on('$ionicView.enter', function (viewInfo, state) {
$scope.articles = _articles;
});
});

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

Resources