Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Two complex problems with our tabs directive
Message
 
 
À
Tous
Information générale
Forum:
Javascript
Catégorie:
Autre
Titre:
Two complex problems with our tabs directive
Divers
Thread ID:
01627325
Message ID:
01627325
Vues:
48
Hi everybody,

My colleague created these directives:
(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,
            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.select = function (uiView) {

                    // call hook before changing state
                    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 != false) {
                        uiView.isActive = true;
                    }
                };

                // called from $stateNotFound, $stateChangeError, $stateChangeAborted
                // and $stateChangeSuccess event listeners
                $rootScope.setNavTabs = function (viewName) {
                    var i = 0;

                    for (i = 0; i < panes.length; i++) {
                        var pane = panes[i];

                        // set to 'false' all but matching name
                        pane.isActive = false;
                        if ((pane.name == viewName)) {

                            // recall hook if stateChangeAborted = true
                            if ($rootScope.stateChangeAborted == true)
                                pane.onActivating(viewName);

                            pane.isActive = 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) {
                        $scope.select(pane);
                    }
                    panes.push(pane);
                };
            },
            templateUrl: 'app/templates/smNavTabs'
        };
    };

    function navTabView($rootScope, $state, $stateParams) {
        return {
            require: '^smNavTabs',
            restrict: 'E',
            transclude: false,
            replace: true,
            scope: {
                name: '@',
                title: '@',
                viewSettings: '@?',
                onActivating: '&?',
                isVisible: '=?'
            },
            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();

                tabsCtrl.addPane(scope);
            },
        };
    };

})()
with the template
<div class="tabbable">
    <ul class="nav nav-pills nav-stacked">
        <li ng-repeat="pane in panes" ng-class="{active:pane.isActive}" ng-show="pane.isVisible">
            <a href="" ng-click="select(pane)" >{{pane.title}}</a>
        </li>
    </ul>
    <div class="tab-content" ng-transclude></div>
</div>
There are, unfortunately, two problems which I don't know how to solve.

1. The invalid tab needs to show in red. This is how it is done in "static" case:
ng-class="{true: 'invalid-tab', false: ''}[form.UserDefinedFields.$invalid]">
More importantly, the invalid tab is not propagating to the whole form and I don't know how to make it work. Say, the first page will show several required columns in red, the Add (Save) button will be disabled. Switching to different tab activates that Add / Save button as the invalid state is not carried over.

2. Similar problem seems to exist with the dirty state which is not propagating to the form. Making control dirty on some tab, then trying to navigate to a different row in the index list doesn't trigger 'Cancel changes' question. I had custom solution but I removed it as I want something generic.

I think both problems can be somehow solved (e.g. saving the current form's state before switching over and restoring), but I don't see a way to access the form from the tab.

Thanks in advance.
If it's not broken, fix it until it is.


My Blog
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform