Search code examples
modal-dialogangularjs-directiveangular-uijquery-ui-timepicker

Angularjs: JQuery UI Directive in Modal leads into troubles


With an angular directive, I create a custom timepicker in my angularjs project. Unfortunately, the timepicker doesn't work properly when using it in a modal, see: http://plnkr.co/edit/QvBHJyoA4O32y9cnsNzE

When opening the modal the first time, everything works fine. But when closing it (by clicking somewhere outside the modal) and opening it again, I see this in the error console:

TypeError: Cannot read property 'timeFormat' of undefined
    at methods.setTime (https://dl.dropboxusercontent.com/u/1004639/stackoverflow/jquery.timepicker.js:222:81)
    at $.fn.timepicker (https://dl.dropboxusercontent.com/u/1004639/stackoverflow/jquery.timepicker.js:821:48)
    at ngModel.$render (http://run.plnkr.co/o2Sj3E7DaqcyasgA/app.js:26:23)
    at Object.<anonymous> (https://dl.dropboxusercontent.com/u/1004639/stackoverflow/angular.min.js:140:131)
    at Object.e.$digest (https://dl.dropboxusercontent.com/u/1004639/stackoverflow/angular.min.js:86:286)
    at Object.e.$apply (https://dl.dropboxusercontent.com/u/1004639/stackoverflow/angular.min.js:88:506)
    at HTMLButtonElement.<anonymous> (https://dl.dropboxusercontent.com/u/1004639/stackoverflow/angular.min.js:144:122)
    at HTMLButtonElement.x.event.dispatch (https://dl.dropboxusercontent.com/u/1004639/stackoverflow/jquery.min.js:5:9843)
    at HTMLButtonElement.y.handle (https://dl.dropboxusercontent.com/u/1004639/stackoverflow/jquery.min.js:5:6626) 

When closing and opening the modal again, I see the error message twice in the console.

I assume the problem has something to do with the render callback (ngModel.$render = ...). It seems that angular tries to render stuff that doesn't exist anymore. But I am not able to fix it. Especially because the directive doesn't know if it is in a modal or not. Therefore, it doesn't make sense to cache a modal close event.


Solution

  • I found a solution. The directive-element has a $destroy event. When this event is called, the $render function can be overwritten with an empty function:

    element.bind("$destroy", function() {
        if (ngModel) {
            ngModel.$render = function() {};
        }
    });
    

    With this additional code snipped, my example works like a charm.