Access form from within Angular $mdDialog
Asked Answered
B

4

10

I am using an Angular 1.5 Material Design $mdDialog in the recommended way, using controllerAs: "dialog". In the template I have a form: <form name="fooForm". Within the template I can access the form with no problem, e.g. ng-disabled="fooForm.$invalid || fooForm.$submitted".

But how do I access that form from within the $mdDialog controller? From what I read, I would expect to be able to do this:

    const doFoo = () => {
        if (this.fooForm.$dirty) {

Here this is the dialog controller.

But I get an error: TypeError: Cannot read property '$dirty' of undefined. And sure enough, if I put a breakpoint in the code, the controller has no fooForm property.

I've tried using $scope as well, but when I put a breakpoint in the code $scope has no fooForm property either.

Here's my dialog template:

<md-dialog aria-label="FooBar">
  <md-toolbar>
    <div class="md-toolbar-tools">
      <h2>FooBar</h2>
      <span flex></span>
      <md-button class="md-icon-button" ng-click="dialog.cancel()">
        <md-icon>close</md-icon>
      </md-button>
    </div>
  </md-toolbar>
  <form name="fooForm" ng-submit="dialog.ok()" novalidate>
    <md-dialog-content>
      <div layout="column" layout-padding>
        <h2 class="md-headline">Foo</h2>
        <div layout="row" layout-xs="column">
          ...
      </div>
    </md-dialog-content>
    <md-dialog-actions>
      <md-button class="md-primary" type="submit" ng-disabled="fooForm.$invalid || fooForm.$submitted">
        OK
      </md-button>
      <md-button ng-click="dialog.cancel()">
        Cancel
      </md-button>
    </md-dialog-actions>
  </form>
</md-dialog>

How do I access a form in an $mdDialog from the dialog controller?

Bani answered 1/2, 2017 at 21:59 Comment(2)
$scope.fooForm ... as usualAvantgarde
Ah, so $scope is still distinct from my controller? I thought that using controllerAs what used to be in $scope was now in my controller. I guess that part still confuses me a bit.Bani
S
5

you need to assign the form to the Scope of the Controller. Do this by changing the form name from fooForm to dialog.fooForm.

<form name="dialog.fooForm" ng-submit="dialog.ok()" novalidate>
Smokeless answered 9/2, 2017 at 8:42 Comment(1)
That was it! I finally tried it today, and it works. Thanks! I want to note that within the form code such as ng-disabled="fooForm.$invalid" will also have to be updated accordingly to ng-disabled="dialog.fooForm.$invalid".Bani
A
2
  1. Scope existed and still exist disregarding controllerAs. When you use 'controllerAs xxx' that just mean - put my controller into scope and name it xxx. You can use them together:
function controller($scope) {
  var vm = this;

  vm.click = function() {}

  $scope.click = function() {}
}

<button ng-click="xxx.click()" ...
<button ng-click="click()" ...
  1. Now if you write ng-click="whatever();smth();"angular will use $parse(expression)(scope) to parse this expression.

  2. Now you write form name="formName" -- angular will use $parse("formName").assign(scope, form); and put it to scope.

  3. $parse is quite clever and can easily handle nested properties, to put form to your controller (as xxx): <form name="xxx.myForm"></form>

Avantgarde answered 2/2, 2017 at 15:22 Comment(4)
But I just set a breakpoint and looked at $scope, and there is no fooForm there, either. Have you tried this with $mdDialog?Bani
Should I guess your template? Or where you log?Avantgarde
I've added the template to the question. The log is irrelevant --- I'm actually putting breakpoint in the code and examining the $scope object.Bani
Where? In the template or in the controller?Bani
D
2

The form is not defined in your controller as a property and therefore you cannot access the form like if (this.fooForm.$dirty).

However you can easily pass it to your method:

const doFoo = (fooForm) => {
    if (fooForm.$dirty) {
    ...

And in html:

ng-click="dialog.cancel(fooForm)"
Deborahdeborath answered 5/2, 2017 at 21:46 Comment(0)
S
-1

Give your controller name when your $mdDialog initialize. see below code:

$scope.showDialog = function (ev) {

    $mdDialog.show({
        controller: 'myController',
        templateUrl: 'template.html',
        parent: angular.element(document.body),
        targetEvent: ev,
        clickOutsideToClose: false,
        fullscreen: false // Only for -xs, -sm breakpoints.
    })
        .then(function (answer) {
            $scope.status = 'You said the information was "' + answer + '".';
        }, function () {
            $scope.status = 'You cancelled the dialog.';
        });
};

Make sure you put controller name in quotes when you create separate controller. like controller: 'myController'

if you want to pass a function then not quotes needed like controller: myController,

In html template use ng-submit="ok()" instead of ng-submit="dialog.ok()".

I have created a sample plnkr with your template and it is working fine. check here

EDIT :`

angular.module('BlankApp', ['ngMaterial']).controller('myController', function($scope, $mdDialog) {
        $scope.ok = function () {
            if ($scope.fooForm.$dirty) {
                // do whatever you want
                $mdDialog.hide("mesage");    
            }
        };  
});`
Sparse answered 10/2, 2017 at 7:36 Comment(2)
Yes, all this was already working fine for me, too. You must have missed the main point of this question: accessing an HTML form on the dialog from the controller.Bani
If you have checked the plnkr link, i have created a controller from where you access form of the dialog. adding that snippet too.Sparse

© 2022 - 2024 — McMap. All rights reserved.