angular / material

Material design for AngularJS
https://material.angularjs.org/
MIT License
16.55k stars 3.39k forks source link

radio-button, select: throw error on $mddialog.show() and cancel() #6048

Open jeson114 opened 8 years ago

jeson114 commented 8 years ago

This happened after i updated my project to RC5 . Every time i close a dialog and try to open it ,it throws Error: [Error] [$compile:ctreq] Controller 'mdRadioGroup', required by directive 'mdRadioButton', can't be found! or Error: [Ara Error] [$compile:ctreq] Controller 'mdSelectMenu', required by directive 'mdOption', can't be found! When the respective elements are present in a form inside the dialog template capture1 capture2

jeson114 commented 8 years ago

There is no problem when i downgrade to 0.11.3

ThomasBurleson commented 8 years ago

Please provide a CodePen or Plunkr that demonstrates this issue.

jeson114 commented 8 years ago

Ok give me a little time . i ll put up a plunker

jeson114 commented 8 years ago

ok while creating the demo i realised that my load functions for md-on-open and similarly the get functions for creating radio buttons were not asynchronous . So instead i used $q in those functions and it works now.

  vm.getLanguages = function () {
        var results = [];
        var deferred = $q.defer();
        masterService.meta('Languages').get().$promise.then(function (data)    {console.log("Languages", data);
            angular.forEach(data.value, function (value, key) {
                results.push({
                    Id: value.Id,
                    Name: value.Name
                });
            });
            deferred.resolve(results);
            console.log(results);
            return deferred.promise;
        });
        vm.languages = results;
        console.log("langs",vm.languages);
        return results;
    }
mohsinmuzawar commented 8 years ago

+1

jeson114 commented 8 years ago

Still facing the same problem [$compile.ctreq] on close and reopen of a $mddialog ..

topherfangio commented 8 years ago

@jeson114 Are you able to create a Codepen demo that we can reproduce the error?

claudiozanin commented 8 years ago

I discovered an other solution described below.

First I placed the HTML of the fields that was throwing the exceptions of Angular inside a NG-REPEAT code, and in JavaScript code of Angular I did a push inside the list when the interface was ready to be built.

Below my HTML before the changes:

<div class="form-group" layout="row" flex>
<md-input-container layout="column" flex>
    <label>Field Name</label>
    <md-select ng-model="service.selectedChart.serieField">
        <md-option ng-repeat="column in columns" ng-value="column.columnName">
            {{column.columnName}}
        </md-option>
    </md-select>
</md-input-container>
</div>

HTML after changes:

<div ng-repeat="control in controls"><div class="form-group" layout="row" flex>
<md-input-container layout="column" flex>
    <label>Field Name</label>
    <md-select ng-model="service.selectedChart.serieField">
        <md-option ng-repeat="column in columns" ng-value="column.columnName">
            {{column.columnName}}
        </md-option>
    </md-select>
</md-input-container>
</div></div>

In JavaScript, before to fill the information in my models to present the options of my md-select I set my NG-REPEAT model with an empty Array, like this:

$scope.controls = [];

After all data got ready to be presented, I just append a new item in my array with this command.

$scope.controls = [{}];

I used this code in 3 places of my application and it worked fine. These fields was in forms placed inside $mdDialog.

Undrium commented 8 years ago

This error occurs when you use a mddialog with a template (containing for instance mdSelect-elements) attached. If this template has a directive linked the mdselect elements will drop this error if dialog is closed down and opened again. I can reproduce this without asynchronous calls, so that's not the problem. Unfortunately plnkr is currently down so I cannot provide an example.

Undrium commented 8 years ago

Created a plnkr, also realised this only occurs if you choose to send the scope with the mdDialog and preserve the scope.

http://plnkr.co/edit/8fgPvsNA5YDgKC9DDYKs

Just open up the dialog twice to reproduce the error.

huseyinalp-zz commented 8 years ago

@Undrium we have same problem. Did you find any solution ?

Undrium commented 8 years ago

@huseyinalp You can probably get around this not using scope, however it would look really ugly if you are dependant of content from scope.

topherfangio commented 8 years ago

@Undrium Thanks for the demo; can definitely see the error.

@EladBezalel Can you please take a look?

KalpanaAr commented 8 years ago

Does someone have a workaround for this issue? I cannot afford to not preservescope, as my modal content is dependent on the parent view. Any help is much appreciated!

sookinoby commented 8 years ago

+1

mmamane commented 7 years ago

+1

chaituGS commented 7 years ago

@KalpanaAr, have you found any solution, i do have the same issue. please share if you got one

SinghB commented 7 years ago

+1

vjku commented 7 years ago

This is a work around I used on facing the same issue - also similar to #6820

Earlier:

        $mdDialog.show({
            controller: filterDialogCtrl,
            controllerAs: 'ctrl',
            locals:{localVars: localVars},  // localVars is other data to pass to the dialog
            bindToController: true,
            templateUrl: './dialogModalPathHere.html',
            parent: angular.element(document.body),
            targetEvent: $event,
            clickOutsideToClose: true,
            scope: $scope,
            preserveScope: true,
        })

I passed $scope as a local var and removed scope and preserveScope params.

Changes after using workaround

        $mdDialog.show({
            controller: dialogCtrl,
            controllerAs: 'ctrl',
            locals:{parentScope: $scope, localVars: localVars},  // localVars is other data to pass to the dialog      
            bindToController: true,
            templateUrl: './dialogModalPathHere.html',
            parent: angular.element(document.body),
            targetEvent: $event,
            clickOutsideToClose: true,
        }) 

Now inside the dialogCtrl, I can access the parent scope as

parentScope.applyFilters(self.dataFromDialogHere);
lmichailian commented 7 years ago

thanks @vjku this works for me

Outflank-Australia commented 7 years ago

@vjku How would I enact your solution when passing an Angular component in a template string as opposed to a templateUrl/Controller format?

hamza-abed commented 6 years ago

I have the same problem, I have tried all solutions but no one works for me. I still have this error showing up the second time I open mdDialog, and my select do not show its value. This error does not mean anything for me.

Error: [$compile:ctreq] Controller 'mdSelectMenu', required by directive 'mdOption', can't be found!

Any working solution?

Thank you

Undrium commented 6 years ago

One solution is to precisely before you close the dialog remove all mentioned formsfields and persist that data, this is however tedious and very impractical. Our projects which are quite large at scale live with this error, not proud of it but it doesn't hurt our applications.

hamza-abed commented 6 years ago

Thank you for your response but can you just explain how to "remove all mentioned formsfields and persist data" ? a little example would be appreciated..

Undrium commented 6 years ago

Not sure I should even assist code-wise here as it's such a bad solution I don't want anyone stumbling into here using it. The dialog-directive has an onclose-callback, within that parse through the dialog-dom and remove the elements (mdSelect for instance), also make sure you have the model-data attached to forms you're removing saved so you can use it elsewhere.

Would recommend to let the directive throw the error instead of doing this "solution".

hamza-abed commented 6 years ago

I understand that, but the problem is that the select don't show its value selected even the first time I open the mdDialog. The second time it shows an error and there is no option selected.

the model of the "input select" did return a value that I send to my database.

Splaktar commented 6 years ago

This seems to be working as expected. Here's an example CodePen of how to do this using locals and the value returned from the dialog's promise.

This is similar to https://github.com/angular/material/issues/6048#issuecomment-276868310, but it's actual working code that you can play with.

Undrium commented 5 years ago

The problem is everything which is a directive within the md-dialog is compiled when the bindings exists and the template is removed, this causes the error. If this is a template it's easily fixed with an ng-if.

$mdDialog.show({
            templateUrl: 'yourAwesomeTemplateContainingDirectives.html',
            scope: $scope,
            preserveScope : true,
            onComplete: function(){$scope.dialogClosed = false;},
            onRemoving: function(){$scope.dialogClosed = true;}
          });

Then in your template do an ng-if="!dialogClosed", sure it removes the animation the second time but you do not have to be bothered by a heck of other teams that the application is broken. I am baffled this has not been looked upon and all the issues it has created has just been closed with either the comment 'Please provide a plunkr' (there are 3, one in the thread) or 'This seems to have been solved'.

Splaktar commented 5 years ago

@Undrium if this is still a problem for you, please open a new issue with a CodePen and reproduction steps.

Undrium commented 5 years ago

@Undrium if this is still a problem for you, please open a new issue with a CodePen and reproduction steps.

I was not replying to your solution, but the entire threads state of this problem. Every application utilizing AngularJS Material which provides directives within their dialogues will get errors dropped once they open/reopen them. The solution you and I have provided (this is the third hack I have written to this) sure sweeps the error under the carpet but also overlooks the fact that scope is lost in it. It has even been addressed by Angular developers as a 'clear problem'.

An example of this is already provided earlier in this thead by me.

Splaktar commented 5 years ago

@Undrium OK, I've re-opened the issue. I'm happy to help someone with their investigation and creation of a PR.