Search code examples
jquerywidgetangularjsusing-directives

Angularjs - Dynamically change dom with directives or widgets?


my goal is to understand how to use angularJS correctly. I want to be able to tie a selection of variable to dynamically changing the DOM structure using angularJS. I dont think I'm quite understanding the documentation that angular provides and I haven't found any examples here or otherwise. Any help is appreciated.

The idea is that I have this use case where I first start with the selection of the type and from that type selected, the appropriate input type elements will be created and then recorded later with the ng-model (from textareas to checkboxes for example), all the while controlled by the angularjs controller for validation/restrictions. I'm used to the idea of having clone-able elements on the page and destroying and creating new with jQuery, but I've been reading that controllers should not have this logic and should instead be created with directives/widgets. I dont see any examples of directives or widgets being manipulated in this way however so I'm not even sure how to proceed. Can I use directives to manipulate the DOM in this way, not just once but multiple times based on a watched element?

Example of what I would like to do.

$scope.types = ['Type1','Type2']

// something along the lines of...
$scope.layouts = {'Type1':['textarea','textarea'], 'Type2':['numeric','datepicker']}

Select Type 1:

  • Show 2 text areas

Select Type 2:

  • Show a numeric input
  • Show a date picker

Solution

  • This is how I would do it. Note that this is a just a starting point. There is still a matter of binding to particular values in the corresponding inputs. I hope it helps.

    Markup:

    <html ng-app="App" ng-controller="MainCtrl">
    
    <body>
    
      <component index="0"></component>
      <component index="1"></component>
      Current type: {{type}}
      <button ng-click="toggleType()">Toggle</button>
    
    </body>
    
    </html>
    

    Directive:

    var ngApp = angular.module('App', []).directive('component', function() {
      var link = function(scope, element, attrs) {
        var render = function() {
          var t = scope.layouts[scope.type][attrs.index];
          if (t === 'textarea') {
            element.html('<' + t + ' /><br>');
          }
          else {
            element.html('<input type="' + t + '"><br>');
          }
        };
        //key point here to watch for changes of the type property
        scope.$watch('type', function(newValue, oldValue) {
          render();
        });
    
        render();
      };
      return {
        restrict : 'E',
        link : link
      }
    });
    

    Controller:

    var MainCtrl = function MainCtrl($scope) {
      $scope.type = 'Type1';
      $scope.types = [ 'Type1', 'Type2' ];
      $scope.layouts = {
        'Type1' : [ 'textarea', 'textarea' ],
        'Type2' : [ 'number', 'text' ]
      };
    
      $scope.toggleType = function() {
        if ($scope.type === 'Type1') {
          $scope.type = 'Type2';
        }
        else {
          $scope.type = 'Type1';
        }
      };
    };