0

I have a directive that works correctly when RequireJS is not used, and I'm trying to migrate it to an application based on RequireJS.

The directive wraps an Angular UI modal, and uses transclude to populate the modal elements (modal elements are defined in the controller that declares the directive). The problem is that if loaded with RequireJS, the modal does not show ANY elements (i.e. it's empty).

This is the plunk of the directive that works correctly without RequireJS. You will see a modal populated with elements.

This is the plunk of the directive that is loaded with RequireJS. You will see that the modal is empty.

There are no errors thrown when the modal is displayed empty, so I'm not sure how to tackle this problem. Any help will be greatly appreciated.

This is the directive:

define(['app','uiBootstrap'], function (app) {

'use strict';
app.directive("theModal", function($timeout,$uibModal) {
          return {
            restrict: "AE",        
            scope: {              
                control: '='
            },
            transclude: true,
            link: function (scope, element, attrs, ctrl, transclude) {

              scope.control = scope.control || {}

                scope.control.openModal = function () {

                var instance = $uibModal.open({
                      animation: false,
                      scope: scope,
                      windowClass: 'the-modal',
                      template: '<div>in the template</div><div class="content"></div>',
                      appendTo: element
                });

                $timeout(function (){
                     transclude(scope.$parent, function(clonedContent){
                       element.find('.content').append(clonedContent);  
                     })
                },10);

                };

            }
          }
    });
});

And this is how I invoke it:

<div ng-controller="ctl">

    <button ng-click="open()">open it!</button>

    <div the-modal control="modalCtl">
        <p>some text</p>
        <input type="text" ng-model="input1" />
    </div>

</div>
1
  • In my opinion, RequireJS does not fit in well with Angular JS. Basically, RequireJS allows you to load resources only when needed. But the thing is, an Angular application needs all its services, controllers, directives, ... when it is bootstrapped. In you case, you don't see any error when testing your app with RequireJS because when Angular compiles the HTML templates, it simply ignores the 'the-modal' directive given it is unknown to your Angular app. Commented Jan 11, 2017 at 11:18

1 Answer 1

1

The issue is you have circular dependency. The app needs your modal module to display things correctly, but your modal directive needs that app. The solution is to load your modal directive into a separate module.

Define a separate Angular Module for Modal

// contents of modal.js (remove app dependency)
define(['uiBootstrap'], function () {
    'use strict';
    var mod = angular.module('modal', ['ui.bootstrap']);
    mod.directive("theModal", function($timeout, $uibModal) {
        return {
            restrict: "AE",        
            scope: {              
                control: '='
            },
            transclude: true,
            link: function (scope, element, attrs, ctrl, transclude){
              // removed code for brevity
            }
        }
    });
    mod.directive("theButton", function($timeout) {
        return {
            restrict: "AE",        
            scope: {              
                control: '='
            },
            transclude: true,
            link: function (scope, element, attrs, ctrl, transclude){
              // removed code for brevity
            }
        }
    });
    return mod;
});

Make app depend on Modal

// contents of app.js
define([
    'angular',
    'uiBootstrap',
    'uiRouter',
    'modal'         // <--- the modal.js directive
], function (angular) {
    'use strict';
     return angular.module('app', ['ui.bootstrap','ui.router', 'modal']); // <--- also add it here
});
Sign up to request clarification or add additional context in comments.

6 Comments

I have a large number of directives in my application, I can't define a module for each one.
You don't have to. You can add them all to modal.js. Just rename it to something sensible.
dozens of directives in a single source file?
by the way, your solution doesn't seem to work, see this plunk: plnkr.co/edit/x9JvywJq772BQaQziApz?p=preview
The problem isn't with the solution. It is with the css in your styles.css. Try this one: plnkr.co/edit/VN2BmWRKVkw8Ixul2bml?p=preview Also, I'm not necessarily recommending you include all the directives in a single file, it is just an option. That would be up to you depending on your use case.
|

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.