Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Two complex problems with our tabs directive
Message
From
12/11/2015 03:40:47
 
General information
Forum:
Javascript
Category:
Other
Miscellaneous
Thread ID:
01627325
Message ID:
01627358
Views:
32
This message has been marked as a message which has helped to the initial question of the thread.
>So, I solved part of the problem (the invalid state (and showing invalid tab in red) as well as disabling the add button.
>
>But I do not like the solution at all as I have to access parent's scope and know the details about form's implementation. Here is all my current code and I'd appreciate suggestions of improving it as it's really bad workaround right now.
>
>
>(function () {
>
>    'use strict';
>
>    var app = angular.module('sysMgrApp')
>    .directive('smNavTabs', ['$rootScope', '$location', '$state', '$stateParams', navTabViews])
>    .directive('smNavTab', ['$rootScope', '$location', '$state', '$stateParams', navTabView]);
>
>    function navTabViews($rootScope, $location, $state, $stateParams) {
>        return {
>            restrict: 'E',
>            
>            transclude: true, // means it has access to the outside scope
>            replace: true,
>            scope: {},
>            
>            controller: function ($scope) {
>                $rootScope.$state = $state;
>                $rootScope.$stateParams = $stateParams;               
>
>                $rootScope.stateChangeAborted = false;
>
>                var urlProtocolAndPath = $location.protocol() + '://' + $location.host() + ($location.port() != NaN ? ':' + $location.port() : '');
>
>                var panes = $scope.panes = [];                
>
>                $scope.lastSelected = 0;
>                $scope.$parent.tabsInvalid = false;
>
>                $scope.select = function (uiView) {                    
>                 //   window.console && console.log('Selecting ' + uiView.name);
>                    // call hook before changing state                                      
>                    
>                    panes[$scope.lastSelected].invalid = uiView.form.$invalid; // all tabs point to the same form
>                                        
>                    uiView.onActivating(uiView.name);
>                   
>                    // use $rootScope to make call to change the state
>                    $rootScope.$state.go(uiView.name, uiView.viewSettings.params, uiView.viewSettings.options);                    
>
>                    // set first call from 'addPane' function
>                    // to default tab
>                    if (panes.length === 0 && uiView.isVisible) {
>                        uiView.isActive = true;
>                    }                   
>
>                };               
>
>                // called from $stateNotFound, $stateChangeError, $stateChangeAborted
>                // and $stateChangeSuccess event listeners
>                $rootScope.setNavTabs = function (viewName) {
>                    var i = 0;
>                 //   window.console && console.log('setNavTabs method is called with viewName = ' + viewName);
>                    $scope.$parent.tabsInvalid = false;
>
>                    for (i = 0; i < panes.length; i++) {
>                        var pane = panes[i];
>
>                        // set to 'false' all but matching name
>                        if (pane.isActive) {
>                            $scope.lastSelected = i;                                                        
>                        }
>                        pane.isActive = false;
>
>                        if ((pane.name == viewName)) {
>
>                            // recall hook if stateChangeAborted = true
>                            if ($rootScope.stateChangeAborted == true)
>                                pane.onActivating(viewName);
>
>                            pane.isActive = true;
>                        }
>
>                        if (pane.invalid)
>                        {
>                            $scope.$parent.tabsInvalid = true;
>                        }
>                    }
>                }
>
>                //onStateChangeStart
>                $rootScope.$on('$stateChangeStart',
>                function (event, toState, toParams, fromState, fromParams) {
>                    // reset stateChangeAborted flag
>                    $rootScope.stateChangeAborted = false;
>                })
>
>                //onStateNotFound
>                $rootScope.$on('$stateNotFound',
>                function (event, unfoundState, fromState, fromParams) {
>                    $rootScope.stateChangeAborted = true;
>                    $rootScope.setNavTabs(fromState.name);
>                })
>
>                //onStateChangeError'
>                $rootScope.$on('$stateChangeError',
>                function (event, toState, toParams, fromState, fromParams) {
>                    $rootScope.stateChangeAborted = true;
>                    $rootScope.setNavTabs(fromState.name);
>                })
>
>                //onStateChangeAborted
>                $rootScope.$on('$stateChangeAborted',
>                function (event, toState, toParams, fromState, fromParams) {
>                    $rootScope.stateChangeAborted = true;
>                    $rootScope.setNavTabs(fromState.name);
>                })
>
>                //onStateChangeSuccess
>                $rootScope.$on('$stateChangeSuccess',
>                function (event, toState, toParams, fromState, fromParams) {
>                    $rootScope.stateChangeAborted = false;
>                    $rootScope.setNavTabs(toState.name);
>                })
>
>                this.addPane = function (pane) {
>                   
>                    if (panes.length === 0 && pane.isVisible) {
>                        panes.push(pane);
>                        $scope.lastSelected = 0;
>                        $scope.select(pane);
>                    }
>                    else
>                        panes.push(pane);
>                };
>
>                
>            },
>            templateUrl: 'app/templates/smNavTabs'
>        };
>    };
>
>    function navTabView($rootScope, $state, $stateParams) {
>        return {
>           
>            require: ['^form','^smNavTabs'],
>            restrict: 'E',
>            transclude: false,
>            replace: true,
>            scope: {
>                name: '@',
>                title: '@',
>                
>                viewSettings: '@?',
>                onActivating: '&?',
>                isVisible: '=?ngShow'
>            },
>            link: function (scope, element, attrs, tabsCtrl) {               
>
>                //default settings and functions
>                var defaultViewSettings = function () {
>                    var params, options;
>                    params = {};
>                    options = {
>                        location: true,
>                        inherit: true,
>                        relative: $state.$current,
>                        notify: true,
>                        reload: false
>                    };
>
>                    return {
>                        params: params,
>                        options: options
>                    };
>                };
>
>                var defaultOnActivating = function () {
>
>                };
>                scope.isVisible = scope.isVisible || true;
>                scope.viewSettings = scope.viewSettings || defaultViewSettings();
>                scope.onActivating = scope.onActivating || defaultOnActivating();
>                scope.form = tabsCtrl[0];
>                scope.invalid = false;
>                scope.isActive = false;
>                tabsCtrl[1].addPane(scope);
>            },
>        };
>    };
>
>})()
>
>and the template is
>
>
><div class="tabbable">
>    <ul class="nav nav-pills nav-stacked">
>        <li ng-repeat="pane in panes" ng-class="{active:pane.isActive, 'invalid-tab':pane.invalid}" ng-show="pane.isVisible">
>            <a href="" ng-click="select(pane)" >{{pane.title}}</a>
>        </li>
>    </ul>
>    <div class="tab-content" ng-transclude></div>
></div>
>
>our forms have the following markup for the add button:
>
>
><button id="btnAdd" class="btn btn-primary" ng-click="new(currentGuest)"
>                                    ng-disabled="form.$invalid || disableAction">
>                                @Labels.add
>                            </button>
>
>the disableAction is actually used when we click on that button (in order to prevent clicking when code didn't complete yet). So, my solution is really a hack.

Not directly applicable to your current implementation but you might look at these:

http://christopherthielen.github.io/ui-router-extras/#/sticky

https://github.com/rpocklin/ui-router-tabs
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform