AngularJS: Access formController of a form placed inside transcluded directive from parent controller

16,276

Solution 1

Because you are using transclude, the directive will create a child transcluded scope. There is no easy path from the controller scope (003) to the directive's transcluded scope (005):

enter image description here

(The hard/not recommended path is to go via private property $$childHead on the controller scope, find the isolate scope, then use $$nextSibling to get to the transcluded scope.)


Update: From insights from this answer, I think we can get the formController inside the directive, then use = to get it to the parent.

scope: { show: '=', formCtrl: '=' },
...
link: function(scope, element) {
   var input1 = element.find('input').eq(0);
   scope.formCtrl = input1.controller('form');
}

HTML:

<div modal show="modal.show" form-ctrl="formCtrl">

Fiddle

enter image description here

Solution 2

Here is my solution: I create such method in parent controller :

$scope.saveForm = function(form) {
  $scope.myForm = form;
};

Then I call it in transcluded content:

<my-directive>
  <form name="myForm">
     <div ng-init="saveForm(myForm)"></div>
  </form>
</my-directive>

After creating directive instance i have form controller instance in parent scope.

Share:
16,276

Related videos on Youtube

MilMly
Author by

MilMly

Updated on June 20, 2022

Comments

  • MilMly
    MilMly about 2 years

    I've created a simple "modal dialog" directive, which uses transclude. I would like to place a form () inside the "modal dialog" directive. I would expect that formController of a form placed inside the directive, is going to be accessible in parent controller's scope, however it isn't. Take a look at the following fiddle, please: http://jsfiddle.net/milmly/f2WMT/1/

    Complete code:

    <!DOCTYPE html>
    <html>
        <head>
            <title>AngJS test</title>
            <link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/foundation/4.0.9/css/foundation.min.css">
            <style>
                .reveal-modal {
                    display: block;
                    visibility: visible;
                }
            </style>
            <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.1.4/angular.min.js"></script>
            <script type="text/javascript">
                var app = angular.module('app', []);
                app.controller('appCtrl', function ($scope) {
                    $scope.model = {
                        id: 1, name: 'John'
                    };
                    $scope.modal = {
                        show: false
                    };
               });
               app.directive('modal', function () {
                   return {
                       scope: {
                           show: '='
                       },
                       transclude: true,
                       replace: true,
                       template: '<div class="reveal-modal small" ng-show="show"><div class="panel" ng-transclude></div></div>'
                   }
               });
           </script>
        </head>
        <body ng-app="app">
            <div ng-controller="appCtrl">
                <div class="panel">
                    Id: {{ model.id }}<br>
                    Name: {{ model.name }}<br>
                    Controller formController: {{ form }}<br>
                    Directive formController: {{ myForm }}<br>
                </div>
    
                <form name="form" class="panel">
                    <input type="text" ng-model="model.name">
                </form>
    
                <a ng-click="modal.show=!modal.show">toggle dialog</a>
    
                <div modal show="modal.show">
                    <form name="myForm">
                        <input type="text" ng-model="model.name">
                    </form>
                </div>
    
            </div>
        </body>
    </html>
    

    So my question is how to access or is it possible to access directive's formController from parent controller?

    Thank you for answers.

    -Milan

    • Langdon
      Langdon about 11 years
      Is that the right fiddle? No reference to $scope.myForm anywhere.
    • MilMly
      MilMly about 11 years
      There's a {{ myForm }} in HTML, which is same as $scope.myForm, I guess.
    • MilMly
      MilMly about 11 years
      There's also {{ form }}, which references a form inside controller but outside of directive. This one works as expected, but myForm does not get to parent scope - appCtrl's scope :-(
    • Langdon
      Langdon about 11 years
      I really think you linked the wrong fiddle. There's no myForm, there's no appCtrl, and there's no formController in that fiddle.
    • MilMly
      MilMly about 11 years
      Yes, you're right, I forgot to update fiddle, thank you for notice. I updated the post with complete source as well as correct fiddle link. Thank you again :-)
  • Langdon
    Langdon about 11 years
    What generated those beautiful graphics?
  • MilMly
    MilMly about 11 years
    Perfect! :) Thank you Mark. I forked your fiddle to make it more general, so it looks for the form element instead of the first input: jsfiddle.net/milmly/utnd6
  • Mark Rajcok
    Mark Rajcok about 11 years
    @Langdon, I have a tool that I wrote/am writing. I use GraphViz's dot to generate the pictures. I have a directive that figures out the scope properties, and some Python code to generate the dot files.
  • a paid nerd
    a paid nerd about 11 years
    @MarkRajcok I'd love to see this tool when your finished, or at least a sample .dot file where I could copy the styles from! :)
  • Mark Rajcok
    Mark Rajcok about 11 years
    @apaidnerd, here's a sample .dot file. If you want to add a label, see stackoverflow.com/a/15707752/215945
  • Eugene Gluhotorenko
    Eugene Gluhotorenko about 9 years
    No really actually. Angular supposes controllers to deal with only data model. But anyway it is the best hack i found.
  • Mark Rajcok
    Mark Rajcok over 8 years
    @apaidnerd, the tool is finished and on github: Peri$scope.
  • Steve
    Steve about 8 years
    This method works great when you cannot edit the directive, such as when using Angular UI Bootstrap directives. See my issue here which was resolved with your method: stackoverflow.com/questions/37727443/…