Dynamically add tabs to ion-nav-view from json data


#1

Hey there,

I know this problem has been around for 2 or 3 times, but there has never been a solutions, so I thought I might give it a try cause I really need a solution for that.

We are building a service that will enable our customers to manage their apps (change tabs, colours, titles, etc) through a web application. They should be able to configure and select services, which should then appear in their app later on. Just like “Enable FB News (FB Page ID required), enable gallery, enable custom web view (iframe e.g.), etc”.

All these “settings” will be saved in a database which will then be queried through an api by the app at first start. The app should then dynamically generate tabs from the json the api delivered. Just like “News (Facebook), Gallery, Contact, etc…”.

Unfortunately we started to build this with ionic and now ran into the issue, that ion-nav-view cannot be interpolated and needs a hardcoded value. So this for example does not work:

<ion-tab ng-repeat="nav in navigation" icon="{{nav.navIcon}}" title="{{nav.navTitle}}" ui-sref="{{nav.navSref}}">
	<ion-nav-view name="nav.navView"></ion-nav-view>
</ion-tab>

There are ideas to overcome this here:

We tried to use this in our project (the solution in https://github.com/driftyco/ionic/pull/1526 with creating a directive), but it seems that this breaks the ion-back button when navigating through the states and also views will only shop up once, which means that when you change the view (click on another tab), and try to go back to the view from before, nothing happens anymore, and you get presented a plain view although the requested url changed correctly.

Do you have any idea on this (how can tabs become dynamic when using ionic)?

HTML:

 <ion-tabs class="tabs-icon-top">
 <ion-tab ng-repeat="nav in navigation" icon="{{nav.navIcon}}" title="{{nav.navTitle}}" ui-sref="{{nav.navSref}}">
    		<dynamic-nav-view name="nav.navView"></dynamic-nav-view>
  </ion-tab>
  </ion-tabs>
<ui-view></ui-view>

Routing/Directive:

	.state('navigation', {
		url: '/navigation',
		abstract: true,
		templateUrl: 'templates/navigation/tabbed.html',
		controller: 'navigationCtrl'
	})

    .state('navigation.news', {
    	url: '/news',
    	views: {
    		'news': {
    			templateUrl: 'templates/api/facebook/feed/feed.html',
    			// templateUrl: newsTemplateUrl;
    			controller: 'facebookCtrl'
    			// controller: newsCtrl
    		}
    	}
    })

    .state('navigation.contact', {
	url: '/contact',
	views: {
		'contact': {
			templateUrl: 'templates/contact/contact.html',
			controller: 'contactCtrl'
		}
	}
})


/*app.directive('dynamicNavView', function($compile) {
	return {
		restrict: 'ECA',
		priority: -400,
		link: function(scope, $element, $attr, ctrl) {
			var dynamicName = scope.$eval($attr.name);
			$element.html('<ion-nav-view name="' + dynamicName + '"></ion-nav-view>');
			$compile($element.contents())(scope);
		}
	};
});*/

Controller, Service:

app.controller('navigationCtrl', function($scope, navigationFactory){

	// NAVIGATION PARAMETERS WILL BE LOADED HERE
	function getNavigation(){
		navigationFactory.getNavigationData()
		.success(function(data){
			$scope.navigation = data;
		})
		.error(function(){
			console.log('navigationCtrl: Error, could not fetch data from API.')
		});
	};

	getNavigation();
});

app.factory('navigationFactory', function($http){
    	return {
    		getNavigationData: function(){
    			return $http.get('http://nicolaswehmeyer.de/apps/api.php?method=getNavigationData&appId='+appId, { cache: true });
    		}
    	}
    });

If I forgot something, just let me know!

Many thanks in advance!

Many thanks in advance,
Nicolas


#2

Hello. I would like to add the same functionallity as well. Thus I am wondering If you were able to find solution to this ? And if you will be willing to share it with us :smile:? Or maybe someon else solved this?
Best regards :slight_smile:


#3

Hey Rzodkiewka,

unfortunately we were not able to solve this problem. I had the Idea to only use ui-router for the but didn’t try it yet as I hope that there will be a future soon in Ionic that will fix this problem. I also think that it will mess up the framework when I use ui-router for the routing. I think this will break the logic in ionics features like back buttons and so on.

In the end I’m still hoping that someone will tell me a solution for my problem… :smile:

So, is there anyone who has a solution for the dynamic navigation?

Beste regards,
Nicolas


#4

I have found the satisfactory solution for me here:


It works quite well with a bit of personal adjustment


#5

I think I may have found a solution for this use case. The Angular UI router allows you to target views in different states, like the parent state. So my solution was to do the following (based on Ionic’s tabs starter project):

  1. app.js

     .state('tab', {
     url: '/tab',
     abstract: true,
     templateUrl: 'templates/tabs.html', 
     controller: 'TabsCtrl'
       })
    
     .state('tab.dash', {
     url: '/dash',
     views: {
       'content@tab': {
         templateUrl: 'templates/tab-dash.html',
         controller: 'DashCtrl'
       }
     }
     })
    

Notice the new controller in state “tab”, as well as the view referenced in “tab.dash” is now “content@tab”. (To really test this, add a few more states (tab.state2, tab.state3) with their own controllers, and referencing the view “content@tab”.

  1. tabs.html

     <ion-tabs class="tabs-icon-top tabs-color-active-positive">
        <ion-tab title="{{tab.name}}" icon-off="ion-ios-star-outline" icon-on="ion-ios-star" href="#/tab/{{tab.mapping}}" ng-repeat="tab in tabs" type="item-text-wrap" >
       </ion-tab>
     </ion-tabs>
    
     <ion-nav-view name="content" class="content-holder"></ion-nav-view>
    

This works for me. One side effect is that the navigation histories get merged into one.


#6

Hi not wor for me put content@tab in my case I Have in the index this:

and my tab asbtract:



but I reemplace for this: