Search code examples
javascriptangularjsangularjs-scopeangular-materialangular-directive

Use directive with required ^form in an angular-material md-dialog


Plunker available here

I want to include a directive (first directive in the example) with a required ^form in an angular-material md-dialog. When the dialog is shown, there's an error saying the form can't be found:

[$compile:ctreq] Controller 'form', required by directive 'first', can't be found!

I'm using require:^form because I want to validate with ng-messages some fields of the parent form inside the directive. The directive outside the dialog works as expected and the form input is validated correctly, the problem is only happening when I use the directive inside the dialog.

I've tried to include another directive (second directive in the example), without require:^form, and it's displayed correctly in the dialog, but in this case the input cannot be validated.

My question is: is there any way to use a directive with "form required" in a md-dialog when the form is defined outside of the dialog?

I suppose it's because mdDialog is creating its own scope... I've tried passing the current scope, creating a new one, etc. but without success so far.

The problem can be easily reproduced in the attached plunker.

Relevant source for reference:

function first() {
    var directive = {
      restrict: 'EA',
      scope: {
        param: '@'
      },
      require: '^form',
      bindToController: true,
      template: '<md-input-container class="md-block"><label>Street with validation</label><input name="street" ng-model="vm.street" required><div ng-messages="form.street.$error"><div ng-message="required">Required</div></div></md-input-container>',
      controller: FirstController,
      controllerAs: 'first',
      link: function(scope, element, attrs, form) {
        scope.form = form;
      }
    };

    FirstController.$inject = [];

    function FirstController() {
      var first = this;
    }
    return directive;
  }


function openDialogFail(event) {
  $mdDialog.show({
    template: '<md-dialog><md-dialog-content><first/></md-dialog-content></md-dialog>',
    targetEvent: event,
    controller: () => this //,
      // scope: $scope.$new()
  });
}

Thanks in advance for your help!


Solution

  • Extracted from comments:

    I still don't get the use case but does something stop you from wrapping <first /> within a separate <form> like in codepen.io/z00bs/pen/vGaBgm