I am loading some images from db according to the list item click. Everything works fine but before loading image grid template/state, my ionic framework + angularjs app is opening the default state from $urlRouterProvider.otherwise().
How can I prevent this from happening and directly open image grid state?
list item html:
<ion-list id="fotos-list4" ng-show="albums_list">
<ion-item class="item-icon-left item-icon-right calm" id="fotos-list-item4" ng-model="album_name" ng-repeat="item in albums" item="item" href="#/item/{{item.FOLDER}}" ng-click="open_album(item)">
<i class="icon ion-images"></i>
{{item.FOLDER}}
<i class="icon ion-ios-arrow-forward"></i>
</ion-item>
</ion-list>
image grid html
<div class="row" ng-repeat="image in images" ng-if="$index % 2 === 0">
<div class="col col-50" ng-if="$index < images.length">
<img class="grid-thumb" ng-src="http://website.com/{{images[$index].FILE}}" width="100%" ng-click="showImages($index)" />
</div>
<div class="col col-50" ng-if="$index + 1 < images.length">
<img class="grid-thumb" ng-src="http://website.com/{{images[$index + 1].FILE}}" width="100%" ng-click="showImages($index+1)" />
</div>
</div>
routes.js
angular.module('app.routes', [])
.config(function($stateProvider, $urlRouterProvider) {
// DEFAULT PAGE
.state('cadastreSe', {
url: '/page5',
templateUrl: 'templates/cadastreSe.html',
controller: 'cadastreSeCtrl'
})
// LIST ITEMS
.state('suporte', {
cache: false,
url: '/page7',
templateUrl: 'templates/suporte.html',
controller: 'suporteCtrl'
})
// IMAGE GRID
.state('fotos2', {
cache: false,
url: '/page8',
templateUrl: 'templates/fotos2.html',
controller: 'fotos2Ctrl',
params: {
dataToFotos: false
}
})
$urlRouterProvider.otherwise('/page5')
controller.js
.controller('suporteCtrl', ['$scope', '$http', '$state', function ($scope, $http, $state) {
$scope.open_album = function(item){
var dataToPass = {};
$http.post("http://website.com/select-album-by-name.php", {'album_name': item.FOLDER}).then(function(response){
console.log({'album_name': item.FOLDER});
console.log(response);
console.log(JSON.stringify(response));
dataToPass.item = item;
dataToPass.album = response.data;
$state.go('fotos2', {dataToFotos: dataToPass});
});
}
.controller('fotos2Ctrl', ['$scope', '$state', function ($scope, $state) {
$scope.myGoBack = function(){
$state.go('suporte');
}
if(!$state.params.dataToFotos) {
console.log($state.params.dataToFotos);
alert("Error :(");
}else{
console.log($state.params.dataToFotos);
$scope.images = $state.params.dataToFotos.album;
}
When I am working with complex, or even simple routing in angular/ionic, I like to set up a router module similar to what you have in routes.js. The key is to use the run() function, which will only run when your router module is initialized.
angular.module('myapp.router', [])
.run( [ '$state', '$rootScope', function( $state, $rootScope ) {
// you could set the state directly here
$state.go('mystate');
$rootScope.$on( '$stateChangeStart', function( evt, toState, toParams, fromState, fromParams, options ) {
// or dynamically set the state based on logic here
if( userIsLoggedIn ) {
evt.preventDefault(); // prevent routing
$state.go('user.account'); // go to page
}
});
}]);
Related
I have a framework that is supposed to be router agnostic, and while I have gotten it to work with ngRoute, I cannot for the life of me to get it to work with UI Router
The main app module Looks like this:
(function () {
"use strict";
angular.module("app", ["ptFramework", "ui.router", "ngStorage", "ui.bootstrap"]);
})();
The framework is built on three modules using custom directives the first module is the framework module
Here is the module:
(function () {
"use strict";
angular.module("ptFramework", [,"ptMenu", "ptDashboard"]);
})();
The module that I am having trouble with is the Menu module Below is the menu module:
(function () {
"use strict";
angular.module("ptMenu", ["ngAnimate"]);
})();
In index.html I have included a custom directive which looks something like this:
HTML:
<pt-menu>
<pt-menu-item label="Dasboard" icon="fa-tachometer" state="dashboard"></pt-menu-item>
<pt-menu-group label="Patients" icon="fa-users">
<pt-menu-item label="Patients" icon="fa-users" state="patient"></pt-menu-item>
<pt-menu-item label="Enter Results" icon="fa-area-chart" state="enterresults"></pt-menu-item>
<pt-menu-item label="View Results" icon="fa-area-chart" state="viewresults"></pt-menu-item>
</pt-menu-group>
<pt-menu-group label="Providers" icon="fa-user-md">
<pt-menu-item label="Providers" icon="fa-user-md" state="provider"></pt-menu-item>
<pt-menu-item label="Injury Dict." icon="fa-book" state="injurydictionary"></pt-menu-item>
<pt-menu-item label="Excercise Dict." icon="fa-book" state="excercisedictionary"></pt-menu-item>
</pt-menu-group>
<pt-menu-group label="Therapist" icon="fa-user-md">
<pt-menu-item label="Therapist" icon="fa-user-md" state="therapist"></pt-menu-item>
<pt-menu-item label="Program Entry" icon="fa-user-md" state="programentry"></pt-menu-item>
<pt-menu-item label="Results" icon="fa-area-chart" state="results"></pt-menu-item>
<pt-menu-item label="Excercises" icon="fa-bicycle" state="excercise"></pt-menu-item>
</pt-menu-group>
</pt-menu>
Here is the directive for Menu item:
(function () {
"use strict";
angular.module('ptMenu').directive('ptMenuItem', function () {
return {
require: '^ptMenu',
scope: {
label: '#',
icon: '#',
state: '#'
},
templateUrl: 'ext-modules/ptMenu/ptMenuItemTemplate.html',
link: function (scope, el, attr, ctrl) {
scope.isActive = function () {
return el === ctrl.getActiveElement();
};
scope.isVertical = function () {
return ctrl.isVertical() || el.parents('.pt-subitem-section').length > 0;
}
el.on('click', function (evt) {
evt.stopPropagation();
evt.preventDefault();
scope.$apply(function () {
ctrl.setActiveElement(el);
ctrl.setState(scope.state);
});
});
}
};
});
})();
As you can see I have state in the directive so that I can use it in my mark up. There is a el.onclick event that calls the parent controllers setState function.
That controller is here:
ptMenuController:
(function () {
"use strict";
angular.module('ptMenu').controller('ptMenuController',
['$scope', '$rootScope',
function ($scope, $rootScope) {
$scope.isVertical = true;
$scope.openMenuScope = null;
$scope.showMenu = true;
$scope.allowHorizontalToggle = true;
this.getActiveElement = function () {
return $scope.activeElement;
};
this.setActiveElement = function (el) {
$scope.activeElement = el;
};
this.isVertical = function () {
return $scope.isVertical;
}
this.setState = function (state) {
$rootScope.$broadcast('pt-menu-item-selected-event',
{ state: state });
};
This broadcasts to the next controller in the chain which is framework controller.
Framework Controller:
(function () {
"use strict";
angular.module("ptFramework").controller("ptFrameworkController",
['$scope', '$window', '$timeout', '$rootScope', '$state',
function ($scope, $window, $timeout, $rootScope, $state) {
$scope.isMenuVisible = true;
$scope.isMenuButtonVisible = true;
$scope.isMenuVertical = true;
$scope.$on('pt-menu-item-selected-event', function (evt, data) {
$scope.stateString = data.state;
$state.go(data.state);
checkWidth();
broadcastMenuState();
});
This message is getting to the front end with the correct state, but it is complaining about my controller, and when I comment out the controller I get no view
Here is the route config file
(function () {
"use strict";
angular.module('app').config([
'$stateProvider', "$urlRouterProvider", function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state("dashboard", {
url: "/dashboard",
template: "<pta-dashboard></pta-dashboard>"
})
.state("patient", {
url: "/patient",
temlateUrl: "app/patient/patientViewTemplate.html",
controller: "patientController"
})
.state("enterresults", {
url: "/enterresults",
templateUrl: "app/patient/enterResultsTemplate.html",
controller: "patientController"
})
.state("viewresults", {
url: "/viewresults",
templateUrl: "app/patient/viewResultsTemplate.html",
controller: "patientController"
})
.state("provider", {
url: "/provider",
templateUrl: "app/provider/providerVierTemplate.html",
controller: "providerController"
})
.state("injurydictionary", {
url: "/injurydictionary",
templateUrl: "app/provider/injuryDictionaryTemplate,html",
controller: "providerController"
})
.state("excercisedictionary", {
url: "/excercisedictionary",
templateUrl: "app/provider/excerciseDictionaryTemplate.html",
controller: "providerController"
})
.state("therapist", {
url: "/therapist",
templateUrl: "app/therapist/therapistViewTemplate.html",
controller: "therapistController"
})
.state("programentry", {
url: "/programentry",
templateUrl: "app/therapist/programEntryTemplate.html",
controller: "therapistController"
})
.state("results", {
url: "/results",
templateUrl: "app/results/resultsViewTemplate.html",
controller: "resultsController"
})
.state("excercise", {
url: "/excercise",
templateUrl: "app/excercise/excerciseViewTemplate.html",
controller: "excerciseController"
})
.state("programs", {
url: "/programs",
templateUrl: "app/programs/programsViewTemplate.html",
controller: "programsController"
});
$urlRouterProvider.otherwise( "/dashboard");
}
]);
})();
I am stumped on this, as is everybody I have spoken with. I have sucessfully made this work with ngRoute. I should also be getting my directive should be showing up as well. I have my ui-sref in place in the frameworkTemplate.html
<div class="pt-title-bar">
<div class="row">
<div class="pt-logo-area col-sm-6">
<img class="pt-icon" ng-src="{{ iconFile }}" />
<div class="pt-title-area">
<p class="pt-logo-title">{{ title }}</p>
<p class="pt-logo-subtitle">{{ subtitle }}</p>
</div>
<div ng-if="isMenuButtonVisible" ng-click="menuButtonClicked()"
class="pt-collapsed-menu pull-right">
<button type="button" class="btn pt-nav-button">
<i class="fa fa-bars"></i>
</button>
</div>
</div>
<div class="pt-right-side-controls col-sm-6">
<pt-user-profile-small></pt-user-profile-small>
</div>
</div>
Any thoughts or input would be appreciated, I am getting ready to abandon the broadcast all together and go to ui-srefs in the index.html. But that feels like giving up.
Thanks,
John
This is apparently a known issue with UI-Router and custom directives
https://github.com/angular-ui/ui-router/pull/858
I am using UI-Router for an Angular app. I can't seem to find what I am doing wrong. I am also not getting any errors which is making it really difficult for me to debug. Followed the docs as well and I am following their steps. My controller function is working when I don't nest it in a child view. Can someone please direct me to what I am doing wrong? Thanks in advance!
APP.JS
'use strict';
var app = angular.module('americasTopStatesApp', ['ui.router', 'ngAutocomplete']);
app.run(function($state, $rootScope) {
$rootScope.$state = $state;
});
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider
.otherwise('/home');
$stateProvider
//HOME
.state('home', {
url: '/home',
templateUrl: './app/views/homeTmpl.html',
controller: 'homeCtrl'
})
//RANKINGS
.state("rankings", {
url: "/rankings",
templateUrl: './app/views/rankingsTmpl.html',
controller: 'rankingsCtrl'
})
// RANKINGS CHILDREN
.state('rankings.data', {
url: '/data',
templateUrl: './app/views/rankingsDataTmpl.html',
controller: 'rankingsCtrl',
parent: 'rankings'
})
});
CONTROLLER rankingsCtrl
'use strict';
app.controller('rankingsCtrl', function($scope, rankingsService) { //Start Controller
// ***********************************************
// *************** GET LATEST DATA ***************
// ***********************************************
$scope.getAllStateRankings = function() {
rankingsService.getStateRankingsData().then(function(data) {
$scope.showRankings = true;
// console.log("Contoller Data", data);
$scope.states = data;
});
};
$scope.showRankings = false;
$scope.getAllStateRankings();
}); //End Controller
PARENT VIEW rankingsTmpl.html
<div class="rankings-heading">
<h1>America's Top States</h1>
<button ng-click="getAllStateRankings()">
<a ui-sref="rankings.data" id="data" class="btn">Data</a>
</button>
</div>
</div ui-view></div>
Child View (Nested ui-view) rankingsDataTmpl.html
<div class="rankings-container" ng-show="showRankings">
<div class="panel panel-primary" ng-repeat='state in states'>
<div class="panel-heading">
<h3 class="panel-title">{{state.state}}</h3>
</div>
<div class="panel-body">
Economy: {{state.economy}}<br>
Capital Access: {{state.accessToCapital}}<br>
Business: {{state.business}}<br>
Cost of living: {{state.costOfLiving}}<br>
</div>
</div>
</div>
Screen Shot
There is a working plunker
In this case, when we have parent child and angular's UI-Router, we should not use solution based on
parent and child has same controller. // WRONG approach
Because they in fact do have JUST same type. The instance of that type 'rankingsCtrl' in runtime is different.
What we need is:
How do I share $scope data between states in angularjs ui-router?
scope inheritance, driven by reference object, e.g. $scope.Model = {}
There is adjusted controller:
.controller('rankingsCtrl', ['$scope', function($scope) {
$scope.Model = {};
$scope.getAllStateRankings = function() {
//rankingsService.getStateRankingsData().then(function(data) {
$scope.Model.showRankings = true;
// console.log("Contoller Data", data);
$scope.Model.states = data;
//});
};
$scope.Model.showRankings = false;
$scope.getAllStateRankings();
}])
At the end, child can have different controller with its own logic for the child view:
.state("rankings", {
url: "/rankings",
templateUrl: 'app/views/rankingsTmpl.html',
controller: 'rankingsCtrl'
})
// RANKINGS CHILDREN
.state('rankings.data', {
url: '/data',
templateUrl: 'app/views/rankingsDataTmpl.html',
controller: 'rankingsChildCtrl',
parent: 'rankings'
})
Also, the parent view should have fixed div:
// wrong
</div ui-view></div>
// starting tag
<div ui-view></div>
Check it here in action
I'm trying to load images from my json file into my application. Here is a code pen: http://codepen.io/beefman/pen/QbBdVw
Here's my code:
js:
.controller('photoCtrl', function($scope, $ionicModal, $ionicBackdrop, $ionicScrollDelegate, $ionicSlideBoxDelegate, $http) {
$scope.images = [];
$scope.getImages = function() {
$http.get('https://api.myjson.com/bins/37ia6')
.success(function(data) {
$scope.images = data.images;
})
}
html:
<ion-view view-title="Gallery" align-title="center" ng-controller="photoCtrl" >
<ion-content ng-init="getImages()" class="center" class="has-header padding">
<!-- start Under6/7/8/9s Photos -->
<div class="item item-divider">
<i class="ion-images"></i> Under6/7/8/9s Photos
</div>
<a class="item item-list-detail">
<ion-scroll direction="x">
<img on-hold="onHold()" ng-repeat="image in images" ng-src="{{images.src}}" ng-click="showImages($index)" class="image-list-thumb" />
</ion-scroll>
</a>
</ion-content>
</ion-view>
You were missing brackets and semicolons in your code.
Use a coding environment to check your syntax, or implement JSHint, which is a tool that checks your code.
http://codepen.io/anon/pen/bdjXYE
angular.module('ionicApp', ['ionic'])
.config(function($stateProvider, $urlRouterProvider, $ionicConfigProvider) {
$ionicConfigProvider.tabs.position('bottom');
$ionicConfigProvider.navBar.alignTitle('center');
$stateProvider
.state('tabs', {
url: "/tabs",
abstract: true,
templateUrl: "tabs.html"
})
.state('tabs.announcement', {
url: '/announcement',
views: {
home: {
templateUrl: 'announcement.html',
controller: 'photoCtrl'
}
}
})
$urlRouterProvider.otherwise('/tabs/announcement');
})
.controller("photoCtrl", function($scope, $http) {
$scope.data = [];
// $scope.getImages = function() {
console.log("trying to load JSON");
$http.get('https://api.myjson.com/bins/1jovy')
.success(function(data) {
$scope.data = data;
console.log(data);
})
.error(function(error) {
console.log(error)
});
});
I am having an issue with ui router where the state is not being triggered on a url.
On navigation to /#/dashboard/ the $state.current is set to abstract true with no state selected within.
No error messages are being thrown on $stateChangeError
JS -
var app = angular.module('frame', ['ui.router']);
app.config(['$stateProvider', '$locationProvider', function($stateProvider, $locationProvider) {
$stateProvider
.state('dashboard', {
url: '/dashboard/',
views: {
'header#': {
template: 'header'
},
'nav#': {
template: 'nav'
},
'main#': {
template: 'main'
}
}
});
// $locationProvider.html5Mode(true);
}]).
run(['$browser', '$rootScope', '$state', function($browser, $rootScope, $state){
// $browser.baseHref = function() { return '../'; };
$rootScope.$on("$stateChangeError", console.log.bind(console));
console.log(window.location);
$rootScope.state = $state;
}]);
html -
<body>
<div ui-view="header">
</div>
<nav ui-view="nav">
</nav>
<main ui-view="main">
</main>
</body>
Here is a link that throughly explains how to use Absolute Names,
https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views
I'm going to try my best to explain this problem. I am also new to Angular so bear with me.
I have two routes that use the same template...
ExampleApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/logbook/following', {
templateUrl: 'views/surf.html',
})
.when('/logbook/following/:surf_id', {
templateUrl: 'views/surf.html',
})
}]);
with two controllers
AppControllers.controller('LogbookController', function($scope, $http, $location, $routeParams) {
$scope.surfs = null;
// Get feed
$http.get(RestURL + 'feeds?filter=following' ).success(function(data) {
if(typeof $routeParams.surf_id == "undefined") {
if(data.length > 0) {
$location.path('/logbook/following/' + data[0].id);
$scope.loadSurfDetail(data[0].id);
}
}
$scope.surfs = data;
});
});
AppControllers.controller('SurfController', function($scope, $http, $location, $routeParams) {
$scope.loading = false;
// Load surf
$scope.loadSurfDetail = function(surfID) {
$scope.loading = true;
$scope.selectedSurf = null;
// Get surf
$http.get(RestURL + 'surfs/' + surfID).success(function(data) {
$scope.selectedSurf = data;
$scope.loading = false;
});
};
if($routeParams.surf_id) {
$scope.loadSurfDetail($routeParams.surf_id);
}
});
using this template file:
<div class="row">
<div class="logbook col-md-3" ng-controller="LogbookController">
<h1>Logbook</h1>
<ol class="surfs-feed">
<li data-id="{{feedSurf.id}}" ng-repeat="feedSurf in surfs" class="surf">
<a href="#/logbook/following/{{feedSurf.id}}">
<strong>{{feedSurf.user.first_name}} {{feedSurf.user.last_name}}</strong>
</a>
</li>
</ol>
</div>
<div class="surf col-md-9" ng-controller="SurfController">
<p class="alert alert-info" ng-show="loading">
Loading...
</p>
<div class="surf-detail" ng-show="selectedSurf">
<pre>
{{selectedSurf | json}}
</pre>
</div>
</div>
</div>
My issue is that when I load a deep link URL, ie. /logbook/following/:surf_id it will use the same template as /logbook/following (adove) and that will cause the logbook feed to be regenerated each time you load up a new surf. So each time you load the surf, the logbook "blinks" and regenerates.
I would like to know how people have tackled this problem without refreshing the feed of surfs and just updating the detail panel on the right hand side...
Thanks!
In your app config, inject $locationProvider and set its html5Mode parameter to true. Then, route changes will not cause the page to refresh.
ExampleApp.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider
.when('/logbook/following', {
templateUrl: 'views/surf.html',
})
.when('/logbook/following/:surf_id', {
templateUrl: 'views/surf.html',
})
$locationProvider.html5Mode(true);
}]);