Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular avoid code duplication when using `ng-if`

My current implementation:

<div class="outer-class" ng-repeat="item in items">
  <div class="inner-class" ng-if="isShow">
    <div class="inner-class-1">{{item}}</div>
  </div>
  <div ng-if="!isShow" class="inner-class-1">{{item}}</div>
</div>

The above code works, but there is a lot of code repetition:

  1. ng-if is there twice (ng-switch cannot be used since a new element is introduced in between)
  2. <div ng-if="!isShow" class="inner-class-1">{{item}}</div> is repeated twice, just because I do not want the element (<div class="inner-class"></div>) to encapsulate my data, when the ng-if evaluates to false.

I was wondering maybe if there is a better way to re-write the same.

like image 956
Avijit Gupta Avatar asked Jan 06 '16 10:01

Avijit Gupta


People also ask

How do you avoid code duplication?

How to Apply the Guideline. To avoid the problem of duplicated bugs, never reuse code by copying and pasting existing code fragments. Instead, put it in a method if it is not already in one, so that you can call it the second time that you need it.

Can I use two ngIf?

we cannot use two structural directives on same element. Structural directives like ngfor can do complex things with the host element and its childrens. When two directives placed on same element we cannot decide which one takes precedence i.e., which should execute first *ngIf or *ngFor?

What is the use of NG if directive?

Definition and Usage The ng-if directive removes the HTML element if the expression evaluates to false. If the if statement evaluates to true, a copy of the Element is added in the DOM.


1 Answers

In this case you would better off creating a custom directive that could conditionally wrap contents. You could do something like this:

angular.module('demo', []).controller('DemoController', function($scope) {
  $scope.items = [1, 2, 3];
  $scope.isShow = false;
})

.directive('wrapIf', function() {
  return {
    restrict: 'A',
    transclude: true,
    link: function(scope, element, attrs, controller, transclude) {

      var previousContent;

      scope.$watch(attrs.wrapIf, function(newVal) {
        if (newVal) {
          previousContent.parent().append(element);
          element.empty().append(previousContent);
        } else {
          transclude(function(clone, scope) {
            previousContent = clone;
            element.replaceWith(clone);
          });
        }
      })
    }
  };
});
.inner-class, .inner-class-1 {
  padding: 6px;
  background: #DDD;
}
.inner-class-1 {
  background: #34dac3;
}
.outer-class {
  margin-bottom: 6px;
}
<script src="https://code.angularjs.org/1.4.8/angular.js"></script>

<div ng-app="demo" ng-controller="DemoController">

  <p>
    <button ng-click="isShow = !isShow">Toggle isShow ({{ isShow }})</button>
  </p>

  <div class="outer-class" ng-repeat="item in items">
    <div class="inner-class" wrap-if="isShow">
      <div class="inner-class-1" ng-click="test(item)">{{item}}</div>
    </div>
  </div>

</div>
like image 95
dfsq Avatar answered Sep 30 '22 01:09

dfsq