I am working on my first ionic/angularjs app and have hit a snag. I can get the page to load like I want with a tabbed navigation and side menu but the content in the side menu won't show for some reason. It is in the page, I can see it in view source but it will not show no matter what manipulation I try to the styling. Being new to this I am at a loss for what to do now. Below is the code.
Index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title></title>
<link href="lib/ionic/css/ionic.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
<link href="css/ionic.app.css" rel="stylesheet">
-->
<!-- ionic/angularjs js -->
<script src="lib/ionic/js/ionic.bundle.js"></script>
<!-- cordova script (this will be a 404 during development) -->
<script src="cordova.js"></script>
<script src="js/user-object.js"></script>
<script src="js/news-feed-object.js"></script>
<!-- your app's js -->
<script src="js/app.js"></script>
<!-- your controllers js -->
<script src="js/controllers.js"></script>
<script src="js/services.js"></script>
</head>
<body ng-app="wgn">
<ion-nav-bar class="bar-energized nav-title-slide-ios7 ">
<div ng-controller="MenuCtrl">
<ion-side-menus>
<fade-bar></fade-bar>
<ion-pane ion-side-menu-content>
<header class="bar bar-header bar-energized nav-title-slide-ios7">
<button class="button button-icon" ng-click="openLeft()"><i class="icon ion-navicon"></i>
</button>
<h1 class="title">Test App</h1>
</header>
<ion-content has-header="true" padding="true">
<!-- Center content -->
</ion-content>
</ion-pane>
<ion-side-menu side="left">
<header class="bar bar-header bar-dark" fade-header>
<h1>Left</h1>
</header>
<ion-content has-header="true">
<div>Content</div>
<div>Content</div>
<div>Content</div>
<div>Content</div>
<div>Content</div>
<div>Content</div>
<div>Content</div>
<div>Content</div>
</ion-content>
</ion-side-menu>
</ion-side-menus>
</div>
<ion-nav-back-button class="button-icon ion-arrow-left-c ">
</ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view animation="slide-left-t">
</ion-nav-view>
</body>
</html>
tabs.html
<ion-tabs class="tabs-icon-top tabs-energized">
<ion-tab title="Home" icon="ion-home" href="#/tab/events">
<ion-nav-view name="home-tab"></ion-nav-view>
</ion-tab>
<ion-tab title="About" icon="ion-ios7-information" href="#/tab/about">
<ion-nav-view name="about-tab"></ion-nav-view>
</ion-tab>
<ion-tab title="Sign-Out" icon="ion-log-out" href="#/sign-in">
</ion-tab>
</ion-tabs>
app.js
// Ionic Starter App
// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
angular.module('wgn', ['ionic', 'wgn.controllers', 'wgn.services'])
.run(function ($ionicPlatform) {
$ionicPlatform.ready(function () {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if (window.StatusBar) {
StatusBar.styleDefault();
}
});
})
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider.state('signin', {
url: "/sign-in",
templateUrl: "templates/sign-in.html",
controller: 'SignInCtrl'
}).state('forgotpassword', {
url: "/forgot-password",
templateUrl: "templates/forgot-password.html"
}).state('slidemenu', {
url: "/slide-menu.html",
abstract: true,
templateUrl: 'templates/slide-menu.html'
}).state('tabs', {
url: "/tab",
abstract: true,
templateUrl: "templates/tabs.html"
}).state('tabs.home', {
url: "/home",
views: {
'home-tab': {
templateUrl: "templates/home.html",
controller: 'HomeTabCtrl'
}
}
}).state('tabs.eventdetails', {
url: "/eventdetails/:eventid",
views: {
'home-tab': {
templateUrl: "templates/event-details.html",
controller: 'EventDetailsCtrl'
}
}
}).state('tabs.addevents', {
url: "/addevents",
views: {
'home-tab': {
templateUrl: "templates/addevents.html"
}
}
}).state('tabs.about', {
url: "/about",
views: {
'about-tab': {
templateUrl: "templates/about.html"
}
}
}).state('tabs.navstack', {
url: "/navstack",
views: {
'about-tab': {
templateUrl: "templates/nav-stack.html"
}
}
}).state('tabs.contact', {
url: "/contact",
views: {
'contact-tab': {
templateUrl: "templates/contact.html"
}
}
});
$urlRouterProvider.otherwise("/sign-in");
});
controller.js
angular.module('wgn.controllers', [])
.controller('SignInCtrl', function ($scope, $state) {
$scope.signIn = function (user) {
console.log('Sign-In', user);
$state.go('tabs.home');
};
}).controller('HomeTabCtrl', function ($scope, WGNEvents, $ionicModal) {
console.log('HomeTabCtrl');
$scope.wgnEvents = WGNEvents.all();
$scope.user = userObject;
$scope.newsFeedList = newsFeedObjectList;
//Add Event
$ionicModal.fromTemplateUrl('templates/addevents.html', {
scope: $scope,
animation: 'slide-in-up'
}).then(function (modal) {
$scope.modal = modal;
});
$scope.addEvent = function () {
$scope.modal.show();
console.log('show modal');
};
$scope.closeModal = function () {
$scope.modal.hide();
};
//Cleanup the modal when we're done with it!
$scope.$on('$destroy', function () {
$scope.modal.remove();
});
// Execute action on hide modal
$scope.$on('modal.hidden', function () {
// Execute action
});
// Execute action on remove modal
$scope.$on('modal.removed', function () {
// Execute action
});
}).controller('EventDetailsCtrl', function ($scope, WGNEvents, $stateParams) {
console.log('EventDetailsCtrl');
var eventID = $stateParams.eventid;
console.log('event-id: ' + eventID);
$scope.wgnEvents = WGNEvents.get(eventID);
console.log($scope.wgnEvents);
}).controller('HomePageCtrl', function ($scope, WGNEvents, $ionicModal) {
console.log('HomePageCtrl');
$scope.getClass = function (score, par) {
return {
'below-par': (par - score) > 0,
'above-par': (par - score) < 0,
'text-dark': (par - score) == 0
};
}
$scope.getOverUnder = function (score, par) {
var total = score - par;
if (total === 0) {
total = 'E';
} else if (total > 0) {
total = '+' + total;
}
return total;
}
}).controller('MenuCtrl', function($scope) {
// Our controller
})
// The fadeBar directive
.directive('fadeBar', function($timeout) {
return {
restrict: 'E',
template: '<div class="fade-bar"></div>',
replace: true,
link: function($scope, $element, $attr) {
// Run in the next scope digest
$timeout(function() {
// Watch for changes to the openRatio which is a value between 0 and 1 that says how "open" the side menu is
$scope.$watch('sideMenuController.getOpenRatio()', function(ratio) {
// Set the transparency of the fade bar
$element[0].style.opacity = Math.abs(ratio);
});
});
}
}
});
Side Menus should not be in your ionNavBar container. I've got an example here showing how to use SideMenu, Tabs, and Navigation elements together. You're close, its just some things don't really work well when they are placed in the wrong place.
http://codepen.io/gnomeontherun/pen/EfKgJ
Markup
<ion-side-menus>
<ion-pane ion-side-menu-content>
<ion-nav-bar class="bar-positive nav-title-slide-ios7">
<ion-nav-back-button class="button-icon"><span class="icon ion-ios7-arrow-left"></span></ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view></ion-nav-view>
</ion-pane>
<ion-side-menu side="left">
<ion-header-bar class="bar bar-header bar-dark"></ion-header-bar>
<ion-content has-header="true">
<ion-list>
<ion-item href="#/" ng-click="sideMenuController.toggleLeft()">Home</ion-item>
</ion-list>
</ion-content>
</ion-side-menu>
<ion-side-menu side="right" >
<ion-header-bar class="bar bar-header bar-dark" title="Search"></ion-header-bar>
<ion-content has-header="true">
</ion-content>
</ion-side-menu>
</ion-side-menus>
<script id="home.html" type="text/ng-template">
<ion-view title="Home">
<ion-nav-buttons side="right">
<button class="button button-icon button-clear ion-plus" ng-click="openModal()"></button>
</ion-nav-buttons>
<ion-nav-buttons side="left">
<button class="button button-icon button-clear ion-navicon" ng-click="openMenu()"></button>
</ion-nav-buttons>
<ion-tabs class="tabs-positive">
<ion-tab title="Stooges">
<h4>The Stooges</h4>
<ion-list>
<ion-item ng-repeat="stooge in stooges" href="#/{{stooge.name}}">{{stooge.name}}</ion-item>
</ion-list>
</ion-tab>
<ion-tab title="Tab 2">
<h2>Just another tab, for another reason</h2>
</ion-tab>
</ion-tabs>
</ion-view>
</script>
<script id="modal.html" type="text/ng-template">
<div class="modal">
<ion-header-bar class="bar bar-header bar-positive">
<h1 class="title">New Stooge</h1>
<button class="button button-clear button-primary" ng-click="modal.hide()">Cancel</button>
</ion-header-bar>
<ion-content>
<div class="padding">
<div class="list">
<label class="item item-input">
<span class="input-label">Name</span>
<input ng-model="form.name" type="text" name="name" />
</label>
<button class="button button-full button-positive" ng-click="addStooge()">Create</button>
</div>
</div>
</ion-content>
</div>
</script>
<script id="item.html" type="text/ng-template">
<ion-view title="{{item}}">
<ion-content>
<h1>{{item}}</h1>
</ion-content>
</ion-view>
</script>
JavaScript
angular.module('ionicApp', ['ionic'])
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/',
controller: 'HomeCtrl',
templateUrl: 'home.html'
})
.state('item', {
url: '/:item',
controller: 'ItemCtrl',
templateUrl: 'item.html'
});
$urlRouterProvider.otherwise('/');
})
.controller('HomeCtrl', function($scope, $ionicSideMenuDelegate, $ionicModal) {
$scope.stooges = [{name: 'Moe'}, {name: 'Larry'}, {name: 'Curly'}];
$ionicModal.fromTemplateUrl('modal.html', {
animation: 'slide-in-up',
scope: $scope
}).then(function (modal) {
$scope.modal = modal;
});
$scope.openMenu = function () {
$ionicSideMenuDelegate.toggleLeft();
}
$scope.openModal = function () {
$scope.modal.show();
}
$scope.form = {};
$scope.addStooge = function () {
console.log($scope);
$scope.stooges.push({name: $scope.form.name});
$scope.modal.hide();
};
$scope.$on('$destroy', function() {
$scope.modal.remove();
});
})
.controller('ItemCtrl', function ($scope, $stateParams) {
$scope.item = $stateParams.item;
});
Related
So I am following this tutorial to extend the autodesk forge viewer. I have compelted all of the steps and no button is showing, I assume this is due to an error with the loading.
https://forge.autodesk.com/blog/extension-skeleton-toolbar-docking-panel
I have also tried this tutorial, with the same issue:
http://learnforge.autodesk.io/#/viewer/extensions/selection?id=conclusion
My issue is I am not getting an error, the extension just isn't showing... does anyone know why?
I'm assuming theres an error in either the viewer or the index.
Below is my code: (index & forge viewer)
index.html:
<!DOCTYPE html>
<html>
<head>
<title>Autodesk Forge Tutorial</title>
<meta charset="utf-8" />
<!-- Common packages: jQuery, Bootstrap, jsTree -->
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
<script src="/js/MyAwesomeExtension.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" />
<!-- Autodesk Forge Viewer files -->
<link rel="stylesheet" href="https://developer.api.autodesk.com/modelderivative/v2/viewers/style.min.css?v=v6.0" type="text/css">
<script src="https://developer.api.autodesk.com/modelderivative/v2/viewers/viewer3D.min.js?v=v6.0"></script>
<!-- this project files -->
<link href="css/main.css" rel="stylesheet" />
<script src="js/ForgeTree.js"></script>
<script src="js/ForgeViewer.js"></script>
</head>
<body>
<!-- Fixed navbar by Bootstrap: https://getbootstrap.com/examples/navbar-fixed-top/ -->
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
<ul class="nav navbar-nav left">
<li>
<a href="http://developer.autodesk.com" target="_blank">
<img alt="Autodesk Forge" src="//developer.static.autodesk.com/images/logo_forge-2-line.png" height="20">
</a>
</li>
</ul>
</div>
</nav>
<!-- End of navbar -->
<div class="container-fluid fill">
<div class="row fill">
<div class="col-sm-4 fill">
<div class="panel panel-default fill">
<div class="panel-heading" data-toggle="tooltip">
Buckets & Objects
<span id="refreshBuckets" class="glyphicon glyphicon-refresh" style="cursor: pointer"></span>
<button class="btn btn-xs btn-info" style="float: right" id="showFormCreateBucket" data-toggle="modal" data-target="#createBucketModal">
<span class="glyphicon glyphicon-folder-close"></span> New bucket
</button>
</div>
<div id="appBuckets">
tree here
</div>
</div>
</div>
<div class="col-sm-8 fill">
<div id="forgeViewer"></div>
</div>
</div>
</div>
<form id="uploadFile" method='post' enctype="multipart/form-data">
<input id="hiddenUploadField" type="file" name="theFile" style="visibility:hidden" />
</form>
<!-- Modal Create Bucket -->
<div class="modal fade" id="createBucketModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Cancel">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="myModalLabel">Create new bucket</h4>
</div>
<div class="modal-body">
<input type="text" id="newBucketKey" class="form-control"> For demonstration purposes, objects (files) are
NOT automatically translated. After you upload, right click on
the object and select "Translate".
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="createNewBucket">Go ahead, create the bucket</button>
</div>
</div>
</div>
</div>
</body>
</html>
ForgeViewer.js:
var viewerApp;
function launchViewer(urn) {
var options = {
env: 'AutodeskProduction',
getAccessToken: getForgeToken
};
var documentId = 'urn:' + urn;
Autodesk.Viewing.Initializer(options, function onInitialized() {
viewerApp = new Autodesk.Viewing.ViewingApplication('forgeViewer');
viewerApp.registerViewer(viewerApp.k3D, Autodesk.Viewing.Private.GuiViewer3D, { extensions: ['MyAwesomeExtension'] });
viewerApp.loadDocument(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
});
}
function onDocumentLoadSuccess(doc) {
// We could still make use of Document.getSubItemsWithProperties()
// However, when using a ViewingApplication, we have access to the **bubble** attribute,
// which references the root node of a graph that wraps each object from the Manifest JSON.
var viewables = viewerApp.bubble.search({ 'type': 'geometry' });
if (viewables.length === 0) {
console.error('Document contains no viewables.');
return;
}
// Choose any of the available viewables
viewerApp.selectItem(viewables[0].data, onItemLoadSuccess, onItemLoadFail);
}
function onDocumentLoadFailure(viewerErrorCode) {
console.error('onDocumentLoadFailure() - errorCode:' + viewerErrorCode);
}
function onItemLoadSuccess(viewer, item) {
// item loaded, any custom action?
}
function onItemLoadFail(errorCode) {
console.error('onItemLoadFail() - errorCode:' + errorCode);
}
function getForgeToken(callback) {
jQuery.ajax({
url: '/api/forge/oauth/token',
success: function (res) {
callback(res.access_token, res.expires_in)
}
});
}
MyAwesomeExtension.js:
// *******************************************
// My Awesome Extension
// *******************************************
function MyAwesomeExtension(viewer, options) {
Autodesk.Viewing.Extension.call(this, viewer, options);
this.panel = null;
}
MyAwesomeExtension.prototype = Object.create(Autodesk.Viewing.Extension.prototype);
MyAwesomeExtension.prototype.constructor = MyAwesomeExtension;
MyAwesomeExtension.prototype.load = function () {
if (this.viewer.toolbar) {
// Toolbar is already available, create the UI
this.createUI();
} else {
// Toolbar hasn't been created yet, wait until we get notification of its creation
this.onToolbarCreatedBinded = this.onToolbarCreated.bind(this);
this.viewer.addEventListener(av.TOOLBAR_CREATED_EVENT, this.onToolbarCreatedBinded);
}
return true;
};
MyAwesomeExtension.prototype.onToolbarCreated = function () {
this.viewer.removeEventListener(av.TOOLBAR_CREATED_EVENT, this.onToolbarCreatedBinded);
this.onToolbarCreatedBinded = null;
this.createUI();
};
MyAwesomeExtension.prototype.createUI = function () {
var viewer = this.viewer;
var panel = this.panel;
// button to show the docking panel
var toolbarButtonShowDockingPanel = new Autodesk.Viewing.UI.Button('showMyAwesomePanel');
toolbarButtonShowDockingPanel.onClick = function (e) {
// if null, create it
if (panel == null) {
panel = new MyAwesomePanel(viewer, viewer.container,
'awesomeExtensionPanel', 'My Awesome Extension');
}
// show/hide docking panel
panel.setVisible(!panel.isVisible());
};
// myAwesomeToolbarButton CSS class should be defined on your .css file
// you may include icons, below is a sample class:
/*
.myAwesomeToolbarButton {
background-image: url(/img/myAwesomeIcon.png);
background-size: 24px;
background-repeat: no-repeat;
background-position: center;
}*/
toolbarButtonShowDockingPanel.addClass('myAwesomeToolbarButton');
toolbarButtonShowDockingPanel.setToolTip('My Awesome extension');
// SubToolbar
this.subToolbar = new Autodesk.Viewing.UI.ControlGroup('MyAwesomeAppToolbar');
this.subToolbar.addControl(toolbarButtonShowDockingPanel);
viewer.toolbar.addControl(this.subToolbar);
};
MyAwesomeExtension.prototype.unload = function () {
this.viewer.toolbar.removeControl(this.subToolbar);
return true;
};
Autodesk.Viewing.theExtensionManager.registerExtension('MyAwesomeExtension', MyAwesomeExtension);
MyAwesomePanel:
// *******************************************
// My Awesome (Docking) Panel
// *******************************************
function MyAwesomePanel(viewer, container, id, title, options) {
this.viewer = viewer;
Autodesk.Viewing.UI.DockingPanel.call(this, container, id, title, options);
// the style of the docking panel
// use this built-in style to support Themes on Viewer 4+
this.container.classList.add('docking-panel-container-solid-color-a');
this.container.style.top = "10px";
this.container.style.left = "10px";
this.container.style.width = "auto";
this.container.style.height = "auto";
this.container.style.resize = "auto";
// this is where we should place the content of our panel
var div = document.createElement('div');
div.style.margin = '20px';
div.innerText = "My content here";
this.container.appendChild(div);
// and may also append child elements...
}
MyAwesomePanel.prototype = Object.create(Autodesk.Viewing.UI.DockingPanel.prototype);
MyAwesomePanel.prototype.constructor = MyAwesomePanel;
Yes, you are missing the CSS for the Buttons and also the reference to the JS files pertaining to the extensions in your HTML file.
<script src="your_folder/MyExtensionFileName.js"></script>
http://learnforge.autodesk.io/#/viewer/extensions/selection?id=toolbar-css
Check this for the CSS of your extension buttons.
I am new to Ionic and I am struck by this issue.
My issue is if I select any menu from {{menu.menuName}} then it will slide to respective tab but this will happen only if I am in app/home other than this URL above condition will not work.Please help.
menu.html
<ion-side-menu side="left">
<ion-header-bar class="bar-balanced">
<h1 class="title">App</h1>
</ion-header-bar>
<ion-content>
<ion-list>
<ion-item menu-close href="#/app/home">
<i class="icon ion-home"></i> Home
</ion-item>
<ion-item menu-close ng-click="createDirectory()">
<i class="icon ion-android-create"></i> Create Name
</ion-item>
<ion-list ng-controller="HomeCtrl">
<div ng-repeat="menu in mainMenu ">
<ion-item class="item-stable"
ng-click="toggleGroup(menu)"
ng-class="{active: isGroupShown(menu)}" style="color:#11c1f3;">
{{menu.menuName}} <i class="icon" style="position: absolute;
right: 8%;" ng-class="isGroupShown(menu) ? 'ion-minus' : 'ion-plus'"></i>
</ion-item>
<ion-item class="item-accordion"
ng-repeat="($index, directories) in directoryList"
ng-class="{'': $index === current}"
ng-click="changeSlide($index,directoryList)"
ng-show="isGroupShown(menu)" style="color:#E47006;" >
{{directories.directoryName}}
</ion-item>
</div>
</ion-list>
</ion-list>
</ion-content>
Controller.js
$scope.changeSlide = function (index,directoryName)
{
console.log('Slide changed to ' + index);
var data= directoryName[index]
if(data !=null){
var directoryId =data.directoryId;
data.dirId = directoryId;
getImages();
function getImages() {
userService.getImages(data).then(function(response) {
$scope.imageData = response;
$scope.current = index;
$ionicSlideBoxDelegate.slide(index);
},function(error) {
})
}
}
$scope.ready.push(index + ': ' + true);
};
app.js
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('app.home',{
url:'/home',
cache:false,
views:{
'menuContent':{
templateUrl:'templates/home.html',
controller:'HomeCtrl'
}
}
})
.state('app.profileUpdate',{
url:'/profileUpdate',
cache:false,
views:{
'menuContent':{
templateUrl:'templates/profileUpdate.html',
controller:'ProfileUpdate'
}
}
});
$urlRouterProvider.otherwise('/app/home');
});
home.html
<ion-view view-title="Home" hide-back-button="true" style="margin-top: 45px;">
<ion-content scroll="false" style="top:0px;" >
<ion-slide-box slide-tabs-scrollable="true" show-pager="false" on-slide-changed="changeSlide(index,directoryList)" bounce="false" ion-slide-tabs>
<ion-slide ng-repeat="(key, catg) in directoryList" ion-slide-tab-label="{{catg.directoryName}}" style="background-color:white;">
<br><br>
<div class="row gallery">
<div class="col col-33" ng-repeat="element in imageData" ng-click="showImages($index)">
<img ng-src="data:image/jpeg;base64,{{element.imagePath}}" width="100%" />
</div>
</div>
<center ng-if="!ready[key]">
<br>
<ion-spinner></ion-spinner>
</center>
<br></br><br></br><br></br>
</ion-slide>
</ion-slide-box>
</ion-content>
</ion-view>
I have changed methods as mentioned below, I am adding this if in case anyone needs,
fetchDirectories();
function fetchDirectories(){
userService.fetchDirectories()
.then(function(response) {
$scope.directoryList = response;
$scope.lastView = $ionicHistory.backView() ;
if($scope.lastView !=null){
if($scope.lastView.stateName != 'app.home'){
var indexNumber = sessionStorage.getItem("indexNumber");
$scope.changeSlide(indexNumber,$scope.directoryList);
}
}else{
$scope.changeSlide(0,$scope.directoryList);
}
window.dispatchEvent(new Event('resize'));
},
function(errResponse){
}
);
};
$scope.changeSlide
$scope.changeSlide = function (index,directoryName)
{
console.log('Slide changed to ' + index);
if($location.path() == '/app/home'){
console.log($location.path());
var data= directoryName[index]
if(data !=null){
var directoryId =data.directoryId;
data.dirId = directoryId;
getImages();
function getImages() {
userService.getImages(data).then(function(response) {
$scope.imageData = response;
$scope.current = index;
$ionicSlideBoxDelegate.slide(index);
},function(error) {
})
}
}
$scope.ready.push(index + ': ' + true);
}
else if($location.path() != '/app/home'){
sessionStorage.setItem("indexNumber",index);
$state.go('app.home');
}
}
I have the following menu template
The below <ion-side-menus> lives in template/menu/menu.html
<ion-side-menus>
<ion-side-menu-content>
<ion-nav-bar class="bar-stable nav-title-slide-ios7">
<ion-nav-buttons side="left">
<button class="button button-icon button-clear ion-navicon" menu-toggle="left">
</button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-nav-view name="menuContent" animation="slide-left-right"></ion-nav-view>
</ion-side-menu-content>
<ion-side-menu enable-menu-with-back-views="true" side="left">
<ion-header-bar class="bar-assertive">
<h1 class="title">Menu</h1>
</ion-header-bar>
<ion-content>
<div ui-view="leftMenuContent"></div>
</ion-content>
</ion-side-menu>
</ion-side-menus>
When navigating from a html file using the following technique
<ion-view view-title="Nutrition">
<ion-content class="padding">
<button class="button button-full button-calm" ng-click="viewPlans()">Plans
</button>
</ion-content>
</ion-view>
home.controller('NutritionController', function ($state) {
$scope.viewPlans = function () {
$state.go('app.home.nutrition.plan');
};
});
The <ion-side-menus> gets completely removed and replaced with the content that was loaded from the state i.e just one screen without menus on the left.
Navigating from a html file using the following technique
<ion-view view-title="Nutrition">
<ion-content class="padding">
<a ui-sref="app.home.nutrition.plan" class="button button-full button-calm" menu-close>Plans</a>
</ion-content>
</ion-view>
The menu on the left stays there only closes and the content gets loaded into the content part of the menu.
Below is my routes:
.state('app', {
url: '',
abstract: true,
templateUrl: 'template/menu/menu.html',
controller: 'MainCtrl as mainCtrl'
})
.state('app.home', {
url: '/home',
views: {
'menuContent#app': {
templateUrl: 'template/home.html',
controller: "HomeController as homeCtrl"
},
'leftMenuContent#app': {
templateUrl: 'template/menu/left/main.html',
controller: "HomeController as homeCtrl"
}
}
})
.state('app.home.nutrition', {
url: '/nutrition',
views: {
'menuContent#app': {
templateUrl: 'template/nutrition.html',
controller: "NutritionController as nutritionCtrl"
},
'leftMenuContent#app': {
templateUrl: 'template/menu/left/nutritionMenu.html'
}
}
})
.state('app.home.nutrition.plan', {
url: '/plan',
views: {
'menuContent#app': {
templateUrl: 'template/plan/plan.html',
controller: "PlanController as planCtrl"
},
'leftMenuContent#app': {
templateUrl: 'template/menu/left/planMenu.html'
}
}
});
Is there a way that I can keep the menu on the left when doing a ng-click?
I'm new to Angularjs and I got a project on it, but here's where the problem comes, am planning to have a toggle button, when the page loads the sidenav should be opened, and when I click on the toggle button than the sidenav and content both should move together.
I've designed my following code, but in responsive i'm getting issues.
I googled allot, but dint get any code with my requirements.
Fiddle Link
angular
.module('MyApp',['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])
.controller('AppCtrl', function ($scope, $timeout, $mdSidenav, $log) {
$scope.toggleLeft = buildDelayedToggler('left');
$scope.toggleRight = buildToggler('right');
$scope.isOpenRight = function(){
return $mdSidenav('right').isOpen();
};
/**
* Supplies a function that will continue to operate until the
* time is up.
*/
function debounce(func, wait, context) {
var timer;
return function debounced() {
var context = $scope,
args = Array.prototype.slice.call(arguments);
$timeout.cancel(timer);
timer = $timeout(function() {
timer = undefined;
func.apply(context, args);
}, wait || 10);
};
}
/**
* Build handler to open/close a SideNav; when animation finishes
* report completion in console
*/
function buildDelayedToggler(navID) {
return debounce(function() {
// Component lookup should always be available since we are not using `ng-if`
$mdSidenav(navID)
.toggle()
.then(function () {
$log.debug("toggle " + navID + " is done");
});
}, 200);
}
function buildToggler(navID) {
return function() {
// Component lookup should always be available since we are not using `ng-if`
$mdSidenav(navID)
.toggle()
.then(function () {
$log.debug("toggle " + navID + " is done");
});
}
}
})
.controller('LeftCtrl', function ($scope, $timeout, $mdSidenav, $log) {
$scope.close = function () {
// Component lookup should always be available since we are not using `ng-if`
$mdSidenav('left').close()
.then(function () {
$log.debug("close LEFT is done");
});
};
})
.controller('RightCtrl', function ($scope, $timeout, $mdSidenav, $log) {
$scope.close = function () {
// Component lookup should always be available since we are not using `ng-if`
$mdSidenav('right').close()
.then(function () {
$log.debug("close RIGHT is done");
});
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-animate.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-route.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-aria.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-messages.min.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-114/svg-assets-cache.js"></script>
<script src="https://cdn.gitcdn.link/cdn/angular/bower-material/v1.1.1/angular-material.js"></script>
<link href="https://cdn.gitcdn.link/cdn/angular/bower-material/v1.1.1/angular-material.css" rel="stylesheet" />
<link href="https://material.angularjs.org/1.1.1/docs.css" rel="stylesheet" />
<div ng-controller="AppCtrl" layout="column" style="height:500px;" ng-cloak="" class="sidenavdemoBasicUsage" ng-app="MyApp">
<section layout="row" flex="">
<md-sidenav class="md-sidenav-left" md-component-id="left" md-is-locked-open="$mdMedia('gt-md')" md-whiteframe="4">
<md-toolbar class="md-theme-indigo">
<h1 class="md-toolbar-tools">Sidenav Left</h1>
</md-toolbar>
<md-content layout-padding="" ng-controller="LeftCtrl">
<md-button ng-click="close()" class="md-primary" hide-gt-md="">
Close Sidenav Left
</md-button>
<p hide="" show-gt-md="">
This sidenav is locked open on your device. To go back to the default behavior,
narrow your display.
</p>
</md-content>
</md-sidenav>
<md-content flex="" layout-padding="">
<div layout="column" layout-align="top center">
<p>
The left sidenav will 'lock open' on a medium (=960px wide) device.
</p>
<p>
The right sidenav will focus on a specific child element.
</p>
<div>
<md-button ng-click="toggleLeft()" class="md-primary" >
Toggle left
</md-button>
</div>
<div>
<md-button ng-click="toggleRight()" ng-hide="isOpenRight()" class="md-primary">
Toggle right
</md-button>
</div>
</div>
<div flex=""></div>
</md-content>
<md-sidenav class="md-sidenav-right md-whiteframe-4dp" md-component-id="right">
<md-toolbar class="md-theme-light">
<h1 class="md-toolbar-tools">Sidenav Right</h1>
</md-toolbar>
<md-content ng-controller="RightCtrl" layout-padding="">
<form>
<md-input-container>
<label for="testInput">Test input</label>
<input type="text" id="testInput" ng-model="data" md-autofocus="">
</md-input-container>
</form>
<md-button ng-click="close()" class="md-primary">
Close Sidenav Right
</md-button>
</md-content>
</md-sidenav>
</section>
</div>
The container is a flex element, but the sidebar has position absolute applied and so isn't accounted in the flex layout.
Just change it to position relative and it will work
angular
.module('MyApp', ['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])
.controller('AppCtrl', function($scope, $timeout, $mdSidenav, $log) {
$scope.toggleLeft = buildDelayedToggler('left');
$scope.toggleRight = buildToggler('right');
$scope.isOpenRight = function() {
return $mdSidenav('right').isOpen();
};
/**
* Supplies a function that will continue to operate until the
* time is up.
*/
function debounce(func, wait, context) {
var timer;
return function debounced() {
var context = $scope,
args = Array.prototype.slice.call(arguments);
$timeout.cancel(timer);
timer = $timeout(function() {
timer = undefined;
func.apply(context, args);
}, wait || 10);
};
}
/**
* Build handler to open/close a SideNav; when animation finishes
* report completion in console
*/
function buildDelayedToggler(navID) {
return debounce(function() {
// Component lookup should always be available since we are not using `ng-if`
$mdSidenav(navID)
.toggle()
.then(function() {
$log.debug("toggle " + navID + " is done");
});
}, 200);
}
function buildToggler(navID) {
return function() {
// Component lookup should always be available since we are not using `ng-if`
$mdSidenav(navID)
.toggle()
.then(function() {
$log.debug("toggle " + navID + " is done");
});
}
}
})
.controller('LeftCtrl', function($scope, $timeout, $mdSidenav, $log) {
$scope.close = function() {
// Component lookup should always be available since we are not using `ng-if`
$mdSidenav('left').close()
.then(function() {
$log.debug("close LEFT is done");
});
};
})
.controller('RightCtrl', function($scope, $timeout, $mdSidenav, $log) {
$scope.close = function() {
// Component lookup should always be available since we are not using `ng-if`
$mdSidenav('right').close()
.then(function() {
$log.debug("close RIGHT is done");
});
};
});
#sdleft {
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-animate.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-route.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-aria.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-messages.min.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-114/svg-assets-cache.js"></script>
<script src="https://cdn.gitcdn.link/cdn/angular/bower-material/v1.1.1/angular-material.js"></script>
<link href="https://cdn.gitcdn.link/cdn/angular/bower-material/v1.1.1/angular-material.css" rel="stylesheet" />
<link href="https://material.angularjs.org/1.1.1/docs.css" rel="stylesheet" />
<div ng-controller="AppCtrl" layout="column" style="height:500px;" ng-cloak="" class="sidenavdemoBasicUsage" ng-app="MyApp">
<section layout="row" flex="">
<md-sidenav id="sdleft" class="md-sidenav-left" md-component-id="left" md-is-locked-open="$mdMedia('gt-md')" md-whiteframe="4">
<md-toolbar class="md-theme-indigo">
<h1 class="md-toolbar-tools">Sidenav Left</h1>
</md-toolbar>
<md-content layout-padding="" ng-controller="LeftCtrl">
<md-button ng-click="close()" class="md-primary" hide-gt-md="">
Close Sidenav Left
</md-button>
<p hide="" show-gt-md="">
This sidenav is locked open on your device. To go back to the default behavior, narrow your display.
</p>
</md-content>
</md-sidenav>
<md-content flex="" layout-padding="">
<div layout="column" layout-align="top center">
<p>
The left sidenav will 'lock open' on a medium (=960px wide) device.
</p>
<p>
The right sidenav will focus on a specific child element.
</p>
<div>
<md-button ng-click="toggleLeft()" class="md-primary">
Toggle left
</md-button>
</div>
<div>
<md-button ng-click="toggleRight()" ng-hide="isOpenRight()" class="md-primary">
Toggle right
</md-button>
</div>
</div>
<div flex=""></div>
</md-content>
<md-sidenav class="md-sidenav-right md-whiteframe-4dp" md-component-id="right">
<md-toolbar class="md-theme-light">
<h1 class="md-toolbar-tools">Sidenav Right</h1>
</md-toolbar>
<md-content ng-controller="RightCtrl" layout-padding="">
<form>
<md-input-container>
<label for="testInput">Test input</label>
<input type="text" id="testInput" ng-model="data" md-autofocus="">
</md-input-container>
</form>
<md-button ng-click="close()" class="md-primary">
Close Sidenav Right
</md-button>
</md-content>
</md-sidenav>
</section>
</div>
I can't see to get go back transition to work.
I have this abstract view called main that holds this child views.
<div class="bar bar-header bar-stable">
<button class="button button-clear button-positive">Log out</button>
</div>
<div class="clearfix"></div>
<ion-side-menus>
<!-- Center content -->
<ion-side-menu-content style="padding-top: 45px">
<ion-nav-view name="categories"></ion-nav-view>
<ion-nav-view name="products"></ion-nav-view>
<ion-nav-view name="payments"></ion-nav-view>
</ion-side-menu-content>
<!-- Left menu -->
<ion-side-menu expose-aside-when="large" style="padding-top: 45px">
<ion-view>
<ion-content>
<ul class="list has-header" id="itemLists">
</ul>
</ion-content>
</ion-view>
<div class="bar bar-subfooter auto-height" style="padding:0">
<ul class="list">
<li class="item">Total <span class="pull-right" id="total"></span></li>
</ul>
</div>
<div class="bar bar-footer">
<div class="text-center">
<div class="bar bar-footer bar-positive">
<div class="title">Pay</div>
</div>
</div>
</div>
</ion-side-menu>
</ion-side-menus>
This is my app.js that holds all routes.
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services', 'ngStorage'])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if(window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar) {
StatusBar.styleDefault();
}
});
})
.config(function($stateProvider, $urlRouterProvider, $ionicConfigProvider){
$ionicConfigProvider.views.transition('none');
$urlRouterProvider.otherwise('/');
$stateProvider
.state('login',{
url: '/',
templateUrl: 'templates/login.html',
controller: 'loginController'
})
.state('main', {
url: '/main',
templateUrl: 'templates/main.html',
controller: 'mainController',
abstract: true
})
.state('main.categories', {
url: '/categories',
views: {
'categories': {
templateUrl: 'templates/categories.html',
controller: 'categoriesController'
}
}
})
.state('main.products', {
url: '/products/:productId',
views: {
'products': {
templateUrl: 'templates/products.html',
controller: 'productsController'
}
}
})
.state('main.payments', {
url: '/payments',
views: {
'payments': {
templateUrl: 'templates/payments.html',
controller: 'paymentsController'
}
}
})
})
I have this state main.products which a child of the main abstract view.
When I click the pay button on the left-down corner, it takes me to the main.payments view.
This is the code for the main.payments view
<ion-view view-title='Payments'>
<ion-content>
<div class="row">
<div class="col col-25">
Cash
</div>
<div class="col col-25">
Credit Card
</div>
<div class="col col-25">
Discount
</div>
<div class="col col-25">
<button ng-click="cancel()" class="button button-large button-block button-assertive">Cancel</button>
</div>
</div>
<div class="row">
<div class="col col-25">
<button ng-click="goBack()" class="button button-large button-block button-royal">Go Back</button>
</div>
</div>
</ion-content>
Now when I press the go back button the URL in the page changes to the previous page but the view doesn't transition there, until I refresh the page.
This is my payment controller that handles the go back button transition.
.controller('paymentsController', function($scope, $localStorage, $log, $state, $window, $ionicHistory){
$scope.cancel = function(){
$localStorage.total= '';
$state.go('main.categories');
$window.location.reload();
};
$scope.goBack = function(){
$ionicHistory.goBack();
}
})
Main.payments and main.products are adjacent views not child view, although main.payments.view is child of main.payments and main.payments is child of main
So you can't travel to adjacent state.
if you want to traverse you have to specifically mention the $state.go(STATE_NAME); or you can use ui-sref in button itself
Note: add "cache:false" to abstract view