cordova ionic app seems to load controller twice - angularjs

I'm having some issues with an app I'm creating in Cordova (5.3.3) using ionic (1.6.5) and angular js and building for iOS and Android.
I have a menu item that when I click should load the next state with other menu items. However it seems like it loads the next state once without the animation, then loads the state again with the animation resulting in a "jerky" effect. It's best shown in a video I have uploaded here: https://www.youtube.com/watch?v=YCEQeqFyNl4&feature=youtu.be
I was wondering if anybody has an idea of what could be the issue here and where I should start looking, or if there are known bugs about this?
Any help would be appreciated!
// the controller
.controller('ProgramCtrl', ['$scope', 'FacProgram',
function($scope, FacProgram) {
$scope.refresh = function() {
FacProgram.refresh()
.finally(function() {
$scope.$broadcast('scroll.refreshComplete');
});
};
$scope.temp_articles = function() {
return FacProgram.all();
};
}
])
.controller('ProgramDetailCtrl', ['$scope', '$stateParams', 'FacProgram',
function($scope, $stateParams, FacProgram) {
$scope.art = FacProgram.get($stateParams.programId);
}
])
// The factory in a different js file:
.factory('FacProgram', ['$http', '$q', 'FacJson',
function($http, $q, FacJson) {
var temp_articles = [];
function findHeader(src, headTag, index) {
var head = $(src).find(headTag).get(0);
temp_articles[index].headlinethumb = head.textContent;
temp_articles[index].headline = head.textContent;
}
function refresh() {
var q = $q.defer();
... // A fucntion that get's URL's from .json file
////////////////////////////////////////////////////////////
angular.forEach(urls, function(URL, index) {
//add the articles to the dictionary
temp_articles.push({
inx: index,
img: img_logos[index]
});
$http.get(URL)
.then(function(sc) {
// The will parse the html looking for thumbnail text, main body text etc
var src = sc.data.substring(sc.data.indexOf('<html>'));
... // code that parses website for content etc
////////////////////////////////////////////////////////
q.resolve();
},
function() {
q.reject();
});
});
});
return q.promise
}
return {
all: function() {
return temp_articles;
},
get: function(programId) {
return temp_articles[programId];
},
refresh: function() {
console.log('DPG programs refresh triggered');
temp_articles = []; // a catch to prevent duplicates and to allow other templates to use without
//contamination
return refresh()
}
}
}]);
<!-- the start state for progams of the DPG -->
<ion-view>
<ion-content>
<div class="list">
<a class="item item-thumbnail-left item-icon-right item-text-wrap" ng-repeat="art in temp_articles()" href="#/program/{{$index}}">
<img ng-src="{{art.img}}">
<h2 class="padding-top" style="font-weight: 300;">{{art.headlinethumb}}</h2>
<i class="icon ion-chevron-right" style="font-size: 18px"></i>
</a>
</div>
</ion-content>
</ion-view>
<!-- the datailed view of the application -->
<ion-view>
<ion-content>
<div style="text-align: left; padding-top: 30px; padding-left: 20px; padding-right: 20px">
<h2 style="font-weight: 500; font-size: 17px">{{art.headline}}</h2>
</div>
<!--<p style="padding-left: 10px; font-size: 13px; font-weight: 300">Datum</p>-->
<div style="text-align: center">
<img style="max-height: 300px; max-width: 300px; width: auto;" ng-src="{{art.img}}">
</div>
<div class="padding" style="font-weight: 300">
<div ng-bind-html="art.text | hrefToJS"></div>
</div>
</ion-content>
</ion-view>

the same happened to me if you put your controller in app.js try removing it from there and only applying it in controller or viceversa.
your state in app.js should look like this:
.state('state-name', {
url: '/state-name',
templateUrl: "templates/walkthrough/state-name.html"
//Notice no controller here
})

Related

How to call method from one controller to other controller in AngularJs 1.7.x, to refresh the UI data

<style>
.sidebar .logo img {
display: none;
}
.sidebar.active .logo img {
display: inline-block;
}
.sidebar.active .logo .first-letter {
display: none !important;
}
.sidebar .logo .first-letter {
display: block;
}
.first-letter {
margin: 0;
font-size: 30px;
color: red;
}
.logo {
height: 90px;
display: flex;
align-items: center;
justify-content: center;
}
</style>
<div class="logo text-center">
<img src="assets/img/VfinanceSLogo.png" width="150">
<h1 class="first-letter">V</h1>
</div>
<div class="sidebar-wrapper"
data-ng-if="user.userType == Constant.UserType.BORROWER.id">
<ul class="nav">
<li data-ui-sref-active="active"><a href="javascript:void(0)"
data-ui-sref="web.lams.brDashboard"> <i class="material-icons">dashboard</i>
<p class="item-name">Dashboard</p>
</a></li>
<li data-ui-sref-active="active"><a href="javascript:void(0)" data-ui-sref="web.lams.applicationList"> <i class="material-icons">Applications</i>
<p class="item-name">Applications</p></a></li>
<li data-ng-repeat="coApplicant in coApplicantList" data-ui-sref-active="active">
<a href="javascript:void(0)" data-ui-sref="web.lams.coApplicants({id : coApplicant.id, parentUserId : coApplicant.parentUserId})">
<i class="material-icons">{{ coApplicant.id }}</i> <p class="item-name">{{coApplicant.firstName}}</p></a>
</li>
</ul>
</div>
<div class="sidebar-wrapper"
data-ng-if="user.userType == Constant.UserType.LENDER.id">
<ul class="nav">
<li data-ui-sref-active="active"><a href="javascript:void(0)"
data-ui-sref="web.lams.products"> <i class="material-icons">dashboard</i>
<p class="item-name">Dashboard</p>
</a></li>
</ul>
</div>
<div class="sidebar-wrapper"
data-ng-if="user.userType == Constant.UserType.USER_TYPE.id">
<ul class="nav">
<li data-ui-sref-active="active"><a href="javascript:void(0)"
data-ng-click="go()"> <i class="material-icons">Clients</i>
<p class="item-name">Clients</p>
</a></li>
</ul>
</div>
<script>
$('.sidebar').hover(function() {
$('.sidebar').toggleClass('active');
}, function() {
$('.sidebar').toggleClass('active');
})
</script>
Above is my sideBar.html file where I am looping coApplicantList and this list is populated inside sideBarCtrl.js.
angular.module("lams").controller("sideBarCtrl",["$scope","$rootScope","Constant","applicationService",
function($scope,$rootScope,Constant,$state,Notification, applicationService) {
$scope.coApplicantList = [];
$scope.getSideBarMenus = function() {
applicationService.getCoApplicants().then(
function(success) {
console.log("getSideBarMenus :: success");
if (success.data.status == 200) {
$scope.coApplicantList = success.data.data;
}
}, function(error) {});
}
$scope.getSideBarMenus();
}]);
Above is my sideBarCtrl.js file where I am populating the 'coApplicantList' and rendered on sideBar.html
angular.module("lams").controller("coApplicantProfileCtrl", function($scope, $http, ) {
$scope.documentResponse = {};
$scope.createNewCoApplicant = function(){
console.log("createNewCoApplicant");
userService.creatCoApplicantProfile($scope.userData).then(
function(success) {
$scope.isDisable = false;
if(success.data.status == 200){
Notification.info("Co-Applicant Added Successfully !");
$uibModalInstance.close('closed');
applicationService.getSideBarMenus();
$scope.getSideBarMenus(); // I am trying to assume that scope variable which i am having inside my controller is globally declared, How can I call method that will refresh sideBarCtrl.js data and refresh the sideBar.html UI ?
}else{
Notification.error(success.data.message);
}
}, function(error) {
$scope.isDisable = false;
$rootScope.validateErrorResponse(error);
});
}
});
Above is my other controller('coApplicantProfileCtrl.js') where I am adding option that will append to sideBar menus seamlessly.
What I am trying to do is inject sideBarCtrl.js to my 'coApplicantProfileCtrl' controller but this is breaking somewhere else. my objective is to refresh side bar menu items inside success method of createNewCoApplicant() declared inside 'coApplicantProfileCtrl.js'
I tried with factory in sideBarCtrl.js file but that is also failing in injecting inside coApplicantProfileCtrl controller.
Try $emit, which will emit an event
angular.module("lams").controller("coApplicantProfileCtrl", function($scope, $http,$rootScope ) {
$scope.documentResponse = {};
$scope.createNewCoApplicant = function(){
console.log("createNewCoApplicant");
userService.creatCoApplicantProfile($scope.userData).then(
function(success) {
$scope.isDisable = false;
if(success.data.status == 200){
Notification.info("Co-Applicant Added Successfully !");
$uibModalInstance.close('closed');
applicationService.getSideBarMenus();
$rootScope.$emit('refresh-sidebar',data_if_any);
}else{
Notification.error(success.data.message);
}
}, function(error) {
$scope.isDisable = false;
$rootScope.validateErrorResponse(error);
});
}
});
And in sideBarCtrl
angular.module("lams").controller("sideBarCtrl",["$scope","$rootScope","Constant","applicationService",
function($scope,$rootScope,Constant,$state,Notification, applicationService) {
$scope.coApplicantList = [];
$scope.getSideBarMenus = function() {
applicationService.getCoApplicants().then(
function(success) {
console.log("getSideBarMenus :: success");
if (success.data.status == 200) {
$scope.coApplicantList = success.data.data;
}
}, function(error) {});
}
$rootScope.$on('refresh-sidebar',function(event,data){
// you can access 'data_if_any' as 'data' variable
$scope.getSideBarMenus();
})
$scope.getSideBarMenus();
}]);

I have the following code for a popover however when I resize the page, i want to close the popover

My html
<div id="deviceInputContainer">
<div class="row noMarg">
<div class="form col-xs-12" style='padding-left:0px;margin-right:15px;'>
<div class="form col-xs-12 noPad left">
<h2 class="page-title">Certification Projects
<span class='icon-settings-big' style='cursor:pointer;float:right;margin-top:-10px;' title='settings' uib-popover-template="dynamicPopoverPageSettings.templateUrl"
popover-placement="bottom-right" popover-trigger="click outsideClick" popover-class="settingsClass" ></span>
</h2>
</div>
<div class="helpMessage" style="margin-left:-15px;margin-right:-15px;" ng-show="dashboardData.userPreferences.showHelpTextEnabled">
<p class="help-text-content col-sm-12 helpText-color helpText-size" style='margin-bottom:15px;'>Your open projects are listed below- but you can search for other projects if you want. Just
set the search criteria below.</p>
</div>
</div>
</div>
</div>
My controller code to toggle popover and on window resize close popover.
But popover hide is not working on window rezise, can somebody please help me where am i doing wrong
$scope.dynamicPopoverPageSettings = {
templateUrl: 'myPopoverTemplatePageSetting.html',
title: 'Page Settings',
isPopOpen: false,
setIsPopOpen: function() {
$scope.dynamicPopoverPageSettings.isPopOpen = !$scope.dynamicPopoverPageSettings.isPopOpen;
console.log("$scope.dynamicPopoverPageSettings.isPopOpen == " + $scope.dynamicPopoverPageSettings.isPopOpen);
},
setIsPopFalse: function() {
$scope.dynamicPopoverPageSettings.isPopOpen = false;
console.log("$scope.dynamicPopoverPageSettings.isPopOpen == " + $scope.dynamicPopoverPageSettings.isPopOpen);
}
};
var w = angular.element($window);
w.bind('resize', function () {
$('.settingsClass ').popover('hide');
});
When using angular if not using it already id recommend using Angular-Bootstrap-native AngularJS directives based on Bootstrap's markup and CSS. I've included this link to their site, it's the 0.14.3 docs. Also including this Codepen with an example of what I think you're trying to accomplish. Hope it helps, I can always help and modify it further.
function exampleController($scope, $window) {
$scope.popoverVisible = false;
function onResize() {
$scope.popoverVisible = false;
// manuall $digest required as resize event
// is outside of angular
$scope.$digest();
}
function cleanUp() {
angular.element($window).off("resize", onResize);
}
angular.element($window).on("resize", onResize);
$scope.$on("$destroy", cleanUp);
}
angular
.module("example", ["ui.bootstrap"])
.controller("exampleController", exampleController);
html,
.container,
.container-fluid {
width: 100%;
height: 100%;
background-color: #333;
color: #fff;
text-align: center;
button {
margin-top: 10%;
font-weight: bold;
}
button:focus {
outline: 0;
}
.popover {
.popover-title,
.popover-content {
color: #333;
}
}
}
<div class="container-fluid" ng-app="example">
<div class="container" ng-controller="exampleController">
<button uib-popover="I have a title!" popover-title="The title." popover-placement="bottom-right" popover-is-open="popoverVisible" type="button" class="btn btn-primary">
CLICK ME
</button>
</div>
</div>

Showing data from firebase in angularjs

I am having problems showing my data from controller to view in ionic angularjs
this is my code
alkitab.html
<ion-view view-title="Alkitab ">
<ion-content class='has-header' style="padding:2%;" ng-init="loadbiblelist();">
<ion-list>
<div ng-repeat= "data in alkitabdate" style="margin:0 auto; text-align:center; ">
<h4>{{data.tanggal}}</h4>
<br>
<h4>{{data.alkitabs.judulPasal}}</h4>
<br>
<div class="isialkitab" style="line-height:2em; font-size:18px; font-family:Roboto; text-align: justify; -moz-text-align-last: center; text-align-last: left;">
{{data.alkitabs.isi}}
</div>
</div>
</ion-list>
<button class="button-balanced button-block large-button ion-thumbsup" ng-click="submit()"><h4>Saya Sudah Baca Alkitab</h4></button>
</ion-content>
</ion-view>
Controller.js
.controller('AlkitabCtrl', ['$scope', '$rootScope', '$timeout', '$state', '$stateParams', 'Alkitabdetail', function($scope, $rootScope, $timeout, $state, $stateParams, Alkitabdetail) {
var rootRef = new Firebase('https://ayobacaalkitab.firebaseio.com/');
var childAlkitab = rootRef.child('alkitab');
var alkitabId = $stateParams.alkitabId;
console.log(alkitabId);
var bibleidurl = childAlkitab.child(alkitabId);
$scope.loadbiblelist = function() {
bibleidurl.on('value', function(snapshot){
$timeout(function(){
var snapshotVal = snapshot.val();
$scope.alkitabdate=snapshotVal;
console.log($scope.alkitabdate);
});
});
}
}])
the problem is in console.log($scope.alkitabdate) i can see the result from firebase but it not showing when i try it using ionic serve.
any help appreciated.
Thanks.
The problem here is returning result is an object not an array, so you cannot use ng-repeat over an object, what you can do is,
<div style="margin:0 auto; text-align:center; ">
<h4>{{alkitabdate.tanggal}}</h4>
<br>
<h4>{{alkitabdate.alkitabs.judulPasal}}</h4>
<br>
<div class="isialkitab" style="line-height:2em; font-size:18px; font-family:Roboto; text-align: justify; -moz-text-align-last: center; text-align-last: left;">
{{alkitabdate.alkitabs.isi}}
</div>
if your result contains more than one object(i.e array) the code which you have should work.

AngularJS: How to refresh parent controller

When the index.html page is rendered my ApplicationController will be called. When I login (login success)I want to refresh my ApplicationController. How to do it?
I have defined below Controllers in my application.
1)Login
angular.module('aclf').controller('LoginController', LoginController);
// The $inject property is an array of service names to inject.
LoginController.$inject = [ '$location', 'AuthenticationService',
'FlashService' ];
function LoginController($location, AuthenticationService, FlashService) {
var loginController = this;
loginController.login = login;
(function initController() {
// reset login status
AuthenticationService.ClearCredentials();
})();
function login() {
loginController.dataLoading = true;
AuthenticationService.Login(loginController.username,
loginController.password, function(response) {
if (response.username === loginController.username) {
console.log(response.authToken);
AuthenticationService.SetCurrentUser(
loginController.username,
response.authToken, true);
$location.path('/home');
} else {
FlashService.Error(response.message);
loginController.dataLoading = false;
}
});
}
;
}
2)ApplicationCotroller
angular.module('aclf').controller('ApplicationController',
function($scope,$rootScope) {
$scope.currentUser = $rootScope.globals.currentUser;
console.log('Inside ApplicationController');
})
3)HomeController- When home controller rendered I want to refresh the portion, since it contains currentUser.
/**
* Home Controller
*/
angular.module('aclf').controller('HomeController', HomeController);
// The $inject property is an array of service names to inject.
HomeController.$inject = [ 'UserService', '$rootScope' ];
function HomeController(UserService, $rootScope) {
var homeController = this;
homeController.user = null;
initController();
function initController() {
loadCurrentUser();
}
function loadCurrentUser() {
UserService.GetByUsername($rootScope.globals.currentUser.username)
.then(function(user) {
homeController.user = user;
});
}
}
4)This is my index.html page
Here I have defined my ApplicationController on body part. This needs to be refreshed at least after login and logout
<body data-ng-controller="ApplicationController">
<!-- TOPBAR START -->
<div id="layout-topbar" data-ng-show="currentUser">
<ul id="top-menu">
<li>
<span class="Fs22 FontRobotoLight">Welcome {{currentUser.username}} </span>
</li>
<li>
Logout
</li>
</ul>
</div>
<!-- TOPBAR END -->
<div id="wrapper">
<div id="wrapperIndent">
<div id="layout-menu-cover" class="Animated05 ps-container">
<div class="ps-scrollbar-x-rail" style="left: 0px; bottom: 3px;">
<div class="ps-scrollbar-x" style="left: 0px; width: 0px;"></div>
</div>
<div class="ps-scrollbar-y-rail" style="top: 0px; right: 3px;">
<div class="ps-scrollbar-y" style="top: 0px; height: 0px;"></div>
</div>
</div>
<div id="layout-portlets-cover">
<div class="Container96 Fnone MarAuto">
<div class="Container100">
<div class="ContainerIndent">
<div class="EmptyBox10"></div>
<div
data-ng-class="{ 'alert': flash, 'alert-success': flash.type === 'success', 'alert-danger': flash.type === 'error' }"
data-ng-if="flash" data-ng-bind="flash.message"></div>
<div data-ng-view></div>
</div>
</div>
<!-- footer -->
<div class="Container100">
<div class="ContainerIndent TexAlCenter Fs14">
Angular | All Rights Reserved.</div>
</div>
</div>
</div>
</div>
</div>
</body>
PS: I am very new to AngularJS
I have tried with reload page stuff. But it was not working.
I removed Application Controller and used
$routeProvider.when('/home', {
controller : 'HomeController',
templateUrl : 'partials/home.html',
controllerAs : 'homeController',
leftNav : 'partials/left-nav-main.html',
topNav: 'partials/top-nav.html'
})
.when('/login', {
controller : 'LoginController',
templateUrl : 'partials/login.html',
controllerAs : 'loginController'
})
Here the templateUrl property in the route definition references the view template that is loaded in the ng-view directive of the div element. I tried to simulate something similar to what Angular does for our left
and top navigation.
The value of the topNav property is used to load the top navigation view in the topnav div element ("id = top-nav") using the ng-include directive. We do the same for left navigation too. The ng-if directive in the left-nav section is used to hide left navigation if the current route configuration does not define the leftNav property.
The last part of this integration is setting up the currentRoute property and
binding it to ng-include. Angular sets up the ng-view template using the route configuration templateUrl property, but it does not know or care about the topNav and leftNav properties that we have added. We need to write some custom code that binds the navigation URLs with the respective ng-includes directives.
$scope.$on('$routeChangeSuccess', function (e, current, previous) {
$scope.currentRoute = current;
});
Here is my index.html
<div class="navbar navbar-default navbar-fixed-top top-navbar">
<!--Existing html-->
<div id="top-nav-container" class="second-top-nav">
<div id="top-nav" ng-include="currentRoute.topNav"></div>
</div>
</div>
<div class="container-fluid">
<div id="content-container" class="row">
<div class="col-sm-2 left-nav-bar"
ng-if="currentRoute.leftNav">
<div id="left-nav" ng-include="currentRoute.leftNav"></div>
</div>
<div class="col-sm-10 col-sm-offset-2">
<div id="page-content" ng-view></div>
</div>
</div>
</div>
Now the left-nav and top-nav appears only in home page and does not appear in login page.
Well, I think the best practice is to reload the entire page:
If you are using angular-ui/ui-router
$state.reload();
If you use another router
$route.reload();

ng-if /ng-show working only when page loads in ionic

I have a nested state .
The view associated to it my app header.
it looks like this:
<ion-view cache-view="false">
<div class="navbar-fixed-top navbar-header bar bar-header " ng-if="showHeader">
<div class="container row">
{{ showSubHeader}}
<div ng-if="showSubHeader" class="topPull" draggable >
<button ng-if="showSubHeader" class="button-icon"><img src="img/topImg.jpg"></button>
</div>
</div>
</div>
</ion-view>
Now, I want div to be shown when showSubHeader is true.
The expression {{ showSubHeader }} changes from true to false correctly, but div does not hide/show according to value variable.
Is there a way to fix it?
Initially on page load, div shows/hides accordingly but div does not hide when variable value changes after loading.
controller:
.controller('AppCtrl', function($scope, $rootScope, $ionicModal, $timeout, $ionicSlideBoxDelegate, $state) {
$scope.showHeader=true;
$scope.showSubHeader=true;
$scope.checkBill= function(){
$scope.showSubHeader=false;
$state.go('menu.TotalBill')
}
})
Change $scope.showSubHeader=false; to $scope.showSubHeader =!$scope.showSubHeader;, then you will be fine.
Check out my example:
var app = angular.module('app', []);
app.controller('myctrl', ['$scope', function($scope) {
$scope.test = true;
$scope.hidden_test = true;
$scope.click = function() {
$scope.hidden_test = !$scope.hidden_test;
};
}]);
.outer {
background: #e2e2e2;
border: 1px solid #000000;
.inner {
background: #c2c2c2;
border: 1px solid #00aa00;
padding: 1px 0 0 25px;
}
}
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<div ng-app="app">
<div ng-controller="myctrl">
<div class="outer" ng-if="test">
<p>Test</p>
<div class="inner" ng-if="hidden_test">
<p>Hidden Test</p>
</div>
<button ng-click="click()">Click</button>
</div>
</div>
</div>

Resources