Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Two complex problems with our tabs directive
Message
 
 
Information générale
Forum:
Javascript
Catégorie:
Autre
Divers
Thread ID:
01627325
Message ID:
01627355
Vues:
84
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.
If it's not broken, fix it until it is.


My Blog
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform