1

I am trying to create a custom directive to render dropdown(select).

app.directive("uiDropdown", function () {
    return {
        restrict: "E",
        replace: true,
        scope: {
            'model': '=ngModel',
            'readOnly':'=?'

        },
            templateUrl : 'template/dropdownTemplate.html',
        link: function (scope, elem, attrs) {
        }
    };
});

the template is

<span ng-if="!readOnly">
<select ng-model="model"  >   
    <option value="1">One</option>   
    <option value="2">Two</option>   
    <option value="3">Three</option>
</select>

Html code to use the directive is

  <ui-dropdown ng-model="region"  read-only='readOnly'>

The plunker code is plunker

If I remove the code 'ng-if="!readOnly"' from the template file, it is working as expected. If I change from "ng-if" to "ng-show" it is working as well.

Am I missing something here? Actually, the directive is supposed to do much more functionality than the one shown in this example. I perfer to use ng-if instead of ng-show. Please help in resolving this issue.

Sanu
  • 17
  • 1
  • 6

2 Answers2

0

ng-if contains a statement that's either true or false Try

 <ui-dropdown ng-model="region"  read-only='true'>
John
  • 536
  • 6
  • 18
  • readOnly is a variable declared in the controller and the value is false here. Note that I have even tried hard coding the ng-if as ng-if=“true” in the template. It is still not updating the model – Sanu Feb 04 '19 at 17:12
0

It has to do with the fact that ng-if creates its own child scope and then you're using a primitive directly. ng-if will actually create a local model boolean that has no relation to the parent. This would be an issue with ng-if even if it weren't being used via a directive, too.

You can work around this by passing an object and reading/setting a value on that object. Here's a simple example showing that your ng-if issue is not related to the directive and then how you can fix this using an object:

angular.module('app', [])
  .controller('ctrl', function($scope) {
    $scope.readOnly = false;
    $scope.primitive = "1";
    $scope.object = {
      selectedValue: "1"
    };
  })
  .directive('uiDropdown', function() {
    return {
      restrict: 'E',
      templateUrl: 'dropdownTemplate.html',
      scope: {
        model: '=ngModel',
        fieldName: '@',
        readOnly: '=?'
      }
    }
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
  <div>
    <label>Readonly: <input type="checkbox" ng-model="readOnly" /></label>
  </div>
  <div>
    <h1>ng-if with primitive - no directive</h1>
    <h2>This will not work</h2>
    <div>
      Value: {{ primitive }}
    </div>
    <div ng-if="!readOnly">
      <select ng-model="primitive">
        <option value="1">One</option>
        <option value="2">Two</option>
        <option value="3">Three</option>
      </select>
    </div>
  </div>
  <div>
    <h1>ng-if with object - directive</h1>
    <h2>This will work</h2>
    <div>
      Value: {{ object.selectedValue }}
    </div>
    <ui-dropdown ng-model="object" read-only="readOnly" field-name="selectedValue"></ui-dropdown>
  </div>
  <script type="text/ng-template" id="dropdownTemplate.html">
    <div ng-if="!readOnly">
      <select ng-model="model[fieldName]">
        <option value="1">One</option>
        <option value="2">Two</option>
        <option value="3">Three</option>
      </select>
    </div>
  </script>
</div>
Lex
  • 6,758
  • 2
  • 27
  • 42
  • Thanks Lex. It looks like I have to leave with ng-show for now. Otherwise I will end up with lots of work around code as I don't want to hard code the name in the dropdown(like selectedValue - need a one to one mapping with the ng-model name and java entity) – Sanu Feb 04 '19 at 18:47
  • Understandable. I've updated the sample to show how you could also pass in a dynamic property name. Not sure if that will work in your situation though. – Lex Feb 04 '19 at 18:51
  • Thanks! I will definitely try it if I see any noticeable performance issue.Currently I have too many param to my ui-dropdown. `` – Sanu Feb 05 '19 at 05:14
  • I am also facing one more issue. I am not able to provide multiple dynamically in my template. Do you have any suggestion? – Sanu Feb 05 '19 at 05:17