Conclusion in Angular UI Modal not working

The purpose of this plunk is to translate the elements in the Angular UI Modal from the controller, where the modal is wrapped with a directive. The solution must meet the following assumptions:

  • The directive announces the transition of fields. These fields are included in the directive declaration in the HTML markup of the controller.
  • These fields declared in the controller must be displayed in the module.
  • The scope of these fields should be available in the controller (see that I declared the variable input1 in the controller, which should set the value to Modal).
  • I defined a content element to overlap the fields. This item is in a modal template. I am not sure when this template is available for transmission.

To summarize, the goal is to have a set of fields declared in the markup of the HTML controller, and available in modal mode, where the modal ends in the directive, and the control area is managed in the controller. Any ideas would be highly appreciated.

HTML

 <div the-modal control="modalCtl"> <p>some text</p> <input type="text" ng-model="input1" /> </div> <button type="button" ng-click="open()">Open me!</button> 

Javascript

 var app = angular.module("app", ['ui.bootstrap']); app.controller("ctl", function($scope,$timeout) { $scope.modalCtl = {}; $scope.input1 = "abc"; $scope.open = function(){ $scope.modalCtl.openModal(); }; }); app.directive("theModal", function($uibModal) { return { restrict: "AE", scope: { control: "=" }, transclude: true, link: function (scope, element, attrs, ctrl, transclude) { scope.control = scope.control || {} scope.control.openModal = function () { scope.instance = $uibModal.open({ animation: false, scope: scope, template: '<div>in the template</div><div class="content"></div>' }); element.find('.content').append(transclude()); }; } } }); 
+5
source share
3 answers

You came close enough to achieve your goal with transclusion, but there are a few things you need to consider:

  • First of all, according to the UT Bootstrap Docs , the options for $uibModal.open() have the appendTo property, which by default is up to body .

    If appendTo not specified, the modal will be added to the body your page and become a direct child of the body . Therefore, the .content request in your directive via element.find('.content') will not work, because it does not exist there.

  • Secondly, AngularJS comes with jQLite , a light version of jQuery. This implies limited support for most jQuery features. One such case is the .find() method, which only works with tag names.

    In order for it to work with jQuery (although you do not need it, because you could use .children() in the chain to request nested DOM elements), you will need to load jQuery before Angular (which I suppose you already have).

    See AngularJS angular.element at angular.element for more angular.element .

  • Rendering the DOM takes a bit of time for Angular, since it needs to make the correct bindings associated with areas and views, complete the digest cycle, and so on. Therefore, you can immediately request a DOM element that may not have been displayed yet.

    The trick awaiting DOM rendering and the completion of the digest cycle is to associate your DOM code with the $timeout wrapper.

Given the above considerations, the openModal method in the link function of your custom theModal directive should look like this:

 scope.control.openModal = function () { scope.instance = $uibModal.open({ animation: false, scope: scope, template: '<div>in the template</div><div class="content"></div>', /** * Make sure the modal is appended to your directive and NOT `body` */ appendTo: element }); /** * Give Angular some time to render your DOM */ $timeout(function (){ /** * In case jQuery is not available */ // var content = element.children('.modal').children('.modal-dialog').children('.modal-content').children('.content'); /** * Since you have jQuery loaded already */ var content = element.find('.content'); /** * Finally, append the transcluded element to the correct position, * while also making sure that the cloned DOM is bound to the parent scope (ie ctl) */ transclude(scope.$parent, function(clonedContent){ content.append(clonedContent); }); }); }; 

Notice how the transclude function gives you control over how you want to bind some transcoded DOM to the user scope and NOT the default scope. A simple call to transclude() will take the current available scope object - i.e. Scope - to bind the translated DOM.

Demo

+6
source

As the previous answers show, you can use the appendTo property to provide an element of your directive as the parent of the modal. You can โ€œwait for the modal template to displayโ€ using the rendered promise in UibModalIstance. ( Documentation ).

 scope.control.openModal = function () { scope.instance = $uibModal.open({ animation: false, scope: scope, template: '<div>in the template</div><div class="content"></div>', appendTo: element }); // We use the redered promise to make sure // the modal template has been loaded. scope.instance.rendered.then(function (){ // You'll most likely want to pass the `$parent` scope as the first // parameter for proper scope binding with your controller. element.find('.content').append(transclude(scope.$parent)); }); }; 

Here's a modified plunker.

+4
source

transclude: true,

It doesnโ€™t work this way, it will insert any markup defined inside the scope of your directive and place that markup inside your directive template (where you put ngTransclude ). This is not what you (apparently) are trying to do.

What you are looking for is to define a template, assign it a URL, and provide it modally using the templateUrl property.

HTML

 <script type="text/ng-template" id="/some-tpl.html"> <p>some text</p> <input type="text" value="1234" /> </script> 

Js

 $uibModal.open({ animation: false, scope: scope, templateUrl: "/some-tpl.html" // link to template url }) 

Then you can place your directive / your logic inside the controller that you provide modal.

Here is the updated plunger

0
source

Source: https://habr.com/ru/post/1257355/


All Articles