0

I've recently switched markup in few of the forms to use angularJS ui Tabs component. The markups looks like this:

<div class="col-lg-3 col-md-3 panel-container">
                        <tabset vertical="true" type="pills">
                            <tab heading="@Labels.general" select="selectView('general')"  >

                            </tab>

                            <tab heading="@Labels.passes" select="selectView('guestPasses')">

                            </tab>

                            <tab heading="@Labels.history" select="selectView('guestActivity')">

                            </tab>
                            
                            <tab heading="@Labels.userDefined 1"
                                 select="selectView('userDefined1')" >
                            </tab>                     
                            
                            <tab heading="@Labels.userDefined 2"
                                 select="selectView('userDefined2')" >
                            </tab>
                        </tabset>
                    </div>

                    <div class="col-lg-9 col-md-9 panel-container">
                        <div data-ui-view data-autoscroll="false"></div>
                        <div data-ui-view="guestPasses" data-autoscroll="false"></div>
                    </div>

and the controller's code to select a view is the following:

$scope.selectView = function (viewName) {
                if ($scope.isNew) {
                    $state.go('new.' + viewName);
                }
                else {
                    $state.go('edit.' + viewName);
                }
            };

All seems to work well except for this change in behavior comparing with the original implementation - if I make invalid input in one of the controls, switch to another tab, then back, that bad input is gone. The valid input is preserved. I am wondering if it's possible to keep the invalid input this way or not?

13
  • 1
    Check out the allowInvalid option - ng-model-options="{allowInvalid=true}". docs.angularjs.org/api/ng/directive/ngModelOptions Commented Mar 11, 2015 at 16:46
  • Apparently it's a new addition in 1.4 version We're using 1.3.13 version. Last time I've checked the 1.4 was in beta. I may need to re-check, do you know how stable it is? Thanks again. Commented Mar 11, 2015 at 18:24
  • 1
    I think it was added in 1.3, it's listed as available in 1.3.13: code.angularjs.org/1.3.13/docs/api/ng/directive/ngModelOptions You'd have to add this attribute to any fields where you want to allow invalid values (anywhere you have ng-model). Commented Mar 11, 2015 at 18:30
  • I've tried and got errors about parser. It's not liking it for some reason. Commented Mar 11, 2015 at 18:52
  • 1
    I can add the above as an answer. There's another SO question with an option that could apply globally that may be a better fit for you. stackoverflow.com/questions/21345987/… Commented Mar 11, 2015 at 20:00

2 Answers 2

1

Each tab is a separate ui-view with ui-bootstrap and by default invalid values are not applied to the model...so the changes are lost when you navigate to another state/tab. You can override the behavior with ng-model-options with the following

<input type="text" ng-model="model.value" ng-model-options="{allowInvalid:true}" ng-pattern="...">

There's also a similar previous question that provides some options for doing this for globally: How can I override Angular's filtering of invalid form values, forcing Angular to persist the $viewValue to $modelValue?

Sign up to request clarification or add additional context in comments.

Comments

0

I also want to share my solution in case it will help someone. In my controller I defined the following scope variable object array:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    $scope.tabsViews = [{
                index: 1, name: 'general',
                invalid: false, title: resourceFactory.getResource('Labels', 'general')
            },
            {
                index: 2, name: 'guestPasses', invalid: false,
                title: resourceFactory.getResource('Labels', 'passes')
            },
            {
                index: 3, name: 'guestActivity', invalid: false,
                title: resourceFactory.getResource('Labels', 'history')
            },
            {
                index: 4, name: 'userDefined1', invalid: false,
                title: resourceFactory.getResource('Labels', 'userDefined') + ' 1'
            },
            {
                index: 5, name: 'userDefined2', invalid: false,
                title: resourceFactory.getResource('Labels', 'userDefined') + ' 2'
            }];

and also this method to select a view:

$scope.selectView = function (viewIndex) {
                
                var newView = objectFindByKey($scope.tabsViews, 'index', viewIndex);

                if ($scope.previousIndex != null) {
                    $scope.tabsViews[$scope.previousIndex-1]["invalid"] = $scope.form.$invalid;
                }                
                
                $scope.previousIndex = viewIndex; 
                if (newView) {
                 
                    var viewName = newView["name"];
                    if ($scope.isNew) {
                        $state.go('new.' + viewName);
                    }
                    else {
                        $state.go('edit.' + viewName);
                    }
                }
            };

Then I added the following markup in my HTML:

<div class="col-lg-3 col-md-3 panel-container">
                        <tabset vertical="true" type="pills">
                            <tab ng-repeat="tab in tabsViews" select="selectView(tab.index)"
                                 class=" {{tabsViews[tab.index-1]['invalid'] ? 'invalid-tab': 'valid-tab' }}">
                                <tab-heading>{{tab.title}}</tab-heading>

                            </tab>
                        </tabset>
                    </div>

                    <div class="col-lg-9 col-md-9 panel-container">
                        <div data-ui-view data-autoscroll="false"></div>
                        <div data-ui-view="guestPasses" data-autoscroll="false"></div>
                    </div>

and finally this is what I have for the classes in the site.css:

.widget .invalid-tab * {
    background-color: #F9EAF3;
    /*color: #F9EAF3;*/
    color: #d43f3a;
}

    .widget .invalid-tab:hover * {
        background-color: #E06B6C;
        color: #ffffff;
    }

    .valid-tab {
        border-top: none;
    }

That's all - everything works quite nicely. I am getting the desired behavior with my invalid tabs.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.