0

Fiddle

I have two buttons. When pressed it displays a modal, with som text. But I also want to add some html dynamically depending on which button is pressed.

I have tried both $observe and $watch methods, but I'm having problems making it work.

here is my code.

angular.module('TM', [])

.controller('protocolCtrl', function(){
    this.text = 'Now looking at the protocol part';
    this.modalId = 'protocolModal';
})

.controller('categoryCtrl', function(){
    this.text = 'Now looking at the category part';
    this.modalId = "categoryModal";
})

.directive('modalDirective', function(){
    return {
        restrict: 'E',
        scope: {
            ctrl: '=',
            modalId: '@',
        },
        template:  ['<div id="{{modalId}}" class="modal fade" role="dialog">', 
                      '<div class="modal-dialog">',
                        '<div class="modal-content">',
                        '<div class="modal-header">',
                        '<h4 class="modal-title">Modal Header</h4>',
                        '</div>',
                        '<div class="modal-body">',
                        '<p> {{ ctrl.text }} </p>',
                        '</div>',
                        '<div class="modal-footer">',
                        '<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>',
                        '</div>',
                        '</div>', 
                        '</div>',
                        '</div>'].join(''),
        link: function(scope, element, attrs) {
            element.$observe('modalId', function(){
                var modal = element.find('#{{modalId}}');
                if(modal == 'protocolModal'){
                    element.find('#{{modalId}}').append('<div>this is a protocol test...</div>');
                } else {
                    element.find('#{{modalId}}').append('<div>this is a category test...</div>');
                }
            });
        }
    }
});
4
  • You don't need to manually $watch or $observe. If the template is controlled by $scope.modalId, then use ng-if to select what is being displayed, for example: <div ng-if="modalId === 'protocolModal'">protocol test</div> <div ng-if="modalId === 'categoryModal'">category</div>. Commented Jul 21, 2015 at 8:08
  • @NewDev hm, I'll try that as well. But I'd really appreciate it if you could show me what I would need to change in my fiddle to get it working with either $observe or $watch as well :) Commented Jul 21, 2015 at 8:22
  • I don't think there is element.$observe - there is attrs.$observe and scope.$watch. Anyway, here you go: jsfiddle.net/L0jns64m Commented Jul 21, 2015 at 8:33
  • @NewDev you are absolutely right - thank you very much. You can just post this as an answer and I'll accept it :) Commented Jul 21, 2015 at 8:36

3 Answers 3

1

I don't think there is element.$observe - there is attrs.$observe and scope.$watch. You already have modelId on the scope, so let's use that.

Also, instead of the wonky .find by id, inject an element as a placeholder for the template and replaceWith it accordingly:

template: '<div id="{{modalId}}">\
             ...\
             <div class="modal-body">\
               <template-placeholder></template-placeholder>\
             </div>\
           </div>",
link: function(scope, element){
  // ...

  var unwatch = scope.$watch("modalId", function(val){
    var placeholder = element.find('template-placeholder');
    if(val == 'protocolModal'){
       placeholder.replaceWith('<div>this is a protocol test...</div>');
    } else {
      placeholder.replaceWith('<div>this is a category test...</div>');
    }

    unwatch(); // seems like you don't really need to set it again
  }
}
Sign up to request clarification or add additional context in comments.

Comments

0

See i updated your Fiddle

Use attr in link function. because you already given attribute to your html i.e: modal-id="{{pctrl.modalId}}

 <modal-directive ctrl="pctrl" modal-id="{{pctrl.modalId}}"></modal-directive>


  if(attrs.modalId == 'protocolModal'){
     element.find('#{{modalId}}').append('<div>this is a protocol test...</div>');
  } else {
     element.find('#{{modalId}}').append('<div>this is a category test...</div>');
  }

Edit :

use $timeout

$timeout(function () {

                if (attrs.modalId == 'protocolModal') {
                    element.find('#' + attrs.modalId).append('<div>this is a protocol test...</div>');
                } else {
                    element.find('#' + attrs.modalId).append('<div>this is a category test...</div>');
                }

            }, 1000)

Now why $timeout because you are applying template and and at same time your link function append your div so it will not apply your div .So first apply template and then in template append your div


And if you want to show that div in popup content the use this selector. see this example: https://jsfiddle.net/kevalbhatt18/o76hxj69/6/

element.find('#'+attrs.modalId +' .modal-body').append('<div>this is a protocol test...</div>');

4 Comments

@Nilzone- have you checked fiddle ? jsfiddle.net/kevalbhatt18/o76hxj69/3
yes I have - and the divs I'm trying to append doesn't show up in the modal
@Nilzone- i updated my answer see this jsfiddle.net/kevalbhatt18/o76hxj69/5 you can see in inspect it is added your div
@Nilzone- jsfiddle.net/kevalbhatt18/o76hxj69/6 see this both update fiddel and let me know .
0

If your two DOM structure diverses, you can consider using two different templates depending on some parameter value.

templateUrl can be specified as a function, such as:

angular.module('Joy', [])
    .controller('ProfileCtrl', ['$scope', function ($scope) {
    $scope.user = {
        name: 'Elit'
    };
}])
    .directive('profile', [function () {
    return {
        restrict: 'A',
        templateUrl: function (elem, attrs) {
            return 'style-' + attrs.color + '.html';
        }
    };
}]);

And use the directive as:

<div ng-app="Joy" id="play-ground" ng-controller="ProfileCtrl">
    <div profile color="red"></div>
    <div profile color="green"></div>
</div>

In this case, if the color is red, the directive will load template from style-red.html. Otherwise from style-green.html.

In your case, you might maintain a flag in the outside controller. Clicking either button will change this flag value and pass in to the directive. The directive will load different templates accordingly.

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.