Search code examples
htmlangularjsvalidationangularjs-scope

How to have a dynamic show/hide & required/not required control (angularjs)


i'm trying to have a dynamic part of my form starting from a value i get from a http call (and later a select). The form is supposed to be required. That means every single input should be required. Of course, if the value i check on is not the "right" one, a part of the form should be hided and the inputs should be set as non-required (otherwise I can't save the data).

I already did it when the first value arrives (from the http, i just check the value and change the show/hide & required/not required part), but I can't do it on a select (the http value and the select are quite similar, but the select should be full dynamic). I just don't understand why, the mechanic should be exactly the same.

Here the html part:

This is the static value (from http call)

<div class="form-group col-sm-12">
    <label class="form-control-label">Classificazione 1</label>
    <br />
        {{picture.PictureClass.Class}}
</div>

And the rest

<span id="showDiv" ng-show = "false">
    <div class="row">
        <div class="form-group col-sm-12" ng-class="{ 'has-error' : formPicture.ReportingDetail.$invalid && formPicture.ReportingDetail.$touched}">
            <label for="ReportingDetail" class="form-control-label">Analisi Segnalazione</label>
                <select ng-disabled="accessLevelStatus() < 2" 
                        class="form-control" name="ReportingDetail"
                        id="ReportingDetail" placeholder="ReportingDetail"
                        ng-model="picture.ReportingDetail">
                    <option value=""></option>
                    <option value="Segnalazione ambientale">Segnalazione ambientale</option>
                    <option value="Segnalazione di sicurezza">Segnalazione di sicurezza</option>
                    <option value="Segnalazione strutturale">Segnalazione strutturale</option>
                </select>
            </div>
          </div>
          <div class="row">
            <div class="form-group col-sm-12"  ng-class="{ 'has-error' : formPicture.Reason.$invalid && formPicture.Reason.$touched}">
                <label for="Reason" class="form-control-label">Motivazioni</label>
                <textarea ng-disabled="accessLevelStatus() < 2" id="Reason" 
                          class="form-control" name="Reason" 
                          ng-model="picture.Reason">
                </textarea>
          </div>
    </div>
</span>

This is how i manage it

    $scope.picture = ReportingPictureService.pictures.get({id: $stateParams.id}, function (picture) {
        $scope.title = 'Modifica segnalazione';
        $scope.picture.PictureDate = new Date($scope.picture.PictureDate);


        //Se la Classificazione 1 >= 3 (Segnalazione/Segnalazione urgente), allora mostro i campi associati alla segnalazione
        var div = angular.element('#showDiv');
        var reportingDetailInput = angular.element('#ReportingDetail');
        var reasonInput = angular.element('#Reason');

        //Se Classificazione 1 >= 3, allora gli input sono visibili e sono tutti required
        if($scope.picture.PictureClass_ID >= 3) {
            div.attr('ng-show',"true");
            reportingDetailInput.attr('required',"required");
            reasonInput.attr('required',"required");
        }
        else {
            div.attr('ng-show',"false");
            reportingDetailInput.attr('required',"false");
            reasonInput.attr('required',"false");
        }


        //Tengo conto anche di Classificazione 2 e uso le seguenti funzioni per modificare gli attributi degli input e dello span (show and hide)
        $scope.changeClass2 = function() {
            if(picture.PictureClass2_ID >= 3) {
                div.attr('ng-show',"true");
                reportingDetailInput.attr('required',"required");
                reasonInput.attr('required',"required");
            }
            else {
                div.attr('ng-show',"false");
                reportingDetailInput.attr('required',"false");
                reasonInput.attr('required',"false");
            }
        }

        //Funzione che gestisce lo show/hide dei due input
        $scope = div.scope();
        $injector = div.injector();
        $injector.invoke(function($compile) {
            $compile(div)($scope)
        });

        //Funzione che gestisce il required = true/false del campo Analisi Segnalazioni
        $scope = reportingDetailInput.scope();
        $injector = reportingDetailInput.injector();
        $injector.invoke(function($compile) {
           $compile(reportingDetailInput)($scope)
        });

        //Funzione che gestisce il required = true/false del campo Motivazioni
        $scope = reasonInput.scope();
        $injector = reasonInput.injector();
        $injector.invoke(function($compile) {
           $compile(reasonInput)($scope)
        });

        downloadImage($scope.picture);
      })

The span part (the show/hide part, http static value) should be visible (and required) when $scope.picture.PictureClass_ID >= 3. Of course it should be hided (and not required) when $scope.picture.PictureClass_ID < 3.

The $scope.picture.PictureClass2_ID is the same, but it should be changing dynamically with the select function.

The first part works well, but the select part is not working. Any idea on how this is not working?


Solution

  • Instead of manipulating DOM attributes with the controller, use the ng-show and ng-required directives:

    <select ng-disabled="accessLevelStatus() < 2" 
            class="form-control" name="ReportingDetail"
            id="ReportingDetail" placeholder="ReportingDetail"
            ng-model="picture.ReportingDetail"
            ng-show="picture.PictureClass_ID >= 3"
            ng-required="picture.PictureClass_ID >= 3" >
        <option value=""></option>
        <option value="Segnalazione ambientale">Segnalazione ambientale</option>
        <option value="Segnalazione di sicurezza">Segnalazione di sicurezza</option>
        <option value="Segnalazione strutturale">Segnalazione strutturale</option>
    </select>
    

    For more information, see