Skip to content
This repository has been archived by the owner on Sep 10, 2019. It is now read-only.

Allowing modals to have their own template, controller etc #666

Open
Joe-5mith opened this issue Jul 16, 2015 · 10 comments
Open

Allowing modals to have their own template, controller etc #666

Joe-5mith opened this issue Jul 16, 2015 · 10 comments

Comments

@Joe-5mith
Copy link

A particular state contains a button that, when clicked, reveals a modal. This modal may contain a complex form, for example. It might, for example, allow users to select dates to filter search results that appear on main page of the state. There may be several such modal buttons on the main page and a user might not ever open any of them.

Currently, Foundation for Apps seems to ask for all the html and controller logic of the modals to be included in the code for the state. Angular Foundation by Pinecone offers a modal service that allows developers to choose a separate templateUrl and controller when they make a modal.

Is there someway of efficiently and neatly having complex modals, possibly multiple modals, on a state using Foundation for Apps? Is it possible to do so without having a huge html file and a huge controller on state load? Is it possible to only load all the html and js for that modal if the user chooses to open the modal? Is there a particular reason that a modal service for this was not made for Foundation for Apps?

@Joe-5mith Joe-5mith changed the title Allowing modals to have their own template and controller etc Allowing modals to have their own template, controller etc Jul 16, 2015
@Joe-5mith
Copy link
Author

Is there a workaround for this - I see the post has been labelled as a 'feature' request?

@soumak77
Copy link
Contributor

@Joe-5mith Have you tried using the ModalFactory (http://foundation.zurb.com/apps/docs/#!/angular-modules)? If so, are there some feature you're looking for that it's missing? I use it for all my dynamically generated modals and it seems to work great (some issues aside which are being tracked).

@Joe-5mith
Copy link
Author

Thanks @soumak77. The ModalFactory does indeed take care of a lot of it.

However, take the example of a modal that contains a lot of controller logic, such as a modal with a web form. I wish to reuse that modal form. Using ModalFactory, I can write the template html once and reuse it as many times as I like. However, each time I want to use the modal on a state, I would have to rewrite all the controller javascript. Is that right? Is there a way around that?

Also, how does one set the class size of the modal like tiny, large etc?

@soumak77
Copy link
Contributor

@Joe-5mith You can create an angular service to encapsulate the logic for generating a modal (an angular factory would work as well)

angular.module('mymodule').factory('ModalService', function (ModalFactory) {
    return {
      createModalXYZ: createModalXYZ
    };

   function createModalXYZ() {
      return new ModalFactory({
          ...
      });
    }
});

There are some pending changes for modals that are waiting for the next release of the framework. One such change was how to configure the classes for a modal pragmatically. An example was added to the docs for how to use the ModalFactory (https://github.com/zurb/foundation-apps/blob/master/docs/templates/modal.html). The class config property will be available in the next release.

@Joe-5mith
Copy link
Author

Thanks for the quick reply - I'll look the idea of a service that produces a ModalFactory and post back.

@Joe-5mith
Copy link
Author

I still find a major flaw with this approach (although there are messy workarounds). The basic issue is that one cannot access the scope variables for the modal template in the factory. So there should be an option to include a controller for the template like:

$scope.foo = "Bloop!";
$scope.bar = "Blee!";
var config = {
    id: 'your optional id here',
    templateUrl: 'path/to/template',
    controller: 'path/to/controller',      // <-- this is needed
    controllerAs: 'modalCtrl',             // <-- this is needed
    contentScope: {
        foo: $scope.foo,
        bar: $scope.bar
    },
    animationIn: 'slideInFromTop'
}
$scope.modal = new ModalFactory(config);

The need for a controller here is the same as the need for a controller anywhere.

Having said that, I have found the functionality of ModalFactory that does exist good so far.

@soumak77
Copy link
Contributor

soumak77 commented Aug 3, 2015

Do you have a specific use case? Not sure if this will help, but you can also attach functions to the modal scope via the contentScope property. So if you need to do something with the click of a button, you can have the following:

$scope.foo = "Bloop!";
$scope.bar = "Blee!";
var config = {
    id: 'your optional id here',
    templateUrl: 'path/to/template',
    contentScope: {
        foo: $scope.foo,
        bar: $scope.bar,
        clicked: function() {
          // do something with foo and bar
        }
    },
    animationIn: 'slideInFromTop'
}
$scope.modal = new ModalFactory(config);

In your template you can use ng-click="clicked()" to trigger the scope method on the click of the button.

@lunks
Copy link

lunks commented Sep 7, 2015

I also would like something similar to what angular-foundation and angular-bootstrap do.
Main problems with just passing things over contentScope:

  • A common practice in the angular community is to encapsulate my function calls in a controller and define it as a vm (see link for more info). Currently I can't do anything similar due to how ModalFactory creates new modals. I have to use scope functions.
// controller.js
function MyCtrl(modalInstance) {
  var vm = this;
  var vm.close = function() {
    modalInstance.close()
  };
};
<!-- template.html -->
<button ng-click="vm.close()">
  • All logic is defined in the parent controller responsible for creating the modal, not in the modal controller itself. This makes complex modals harder to implement.

A concrete use case:
I have a list of courses in a page, with a New Course button to create a new modal using a courseForm directive, which binds to a function from the current scope on the onSave attribute. On this specific case, I want to track the event using a TrackerService and then close the modal. I'd like to define bind a trackAndClose function to the onSave attribute.

Because I have to pass any functions I'd like to use via the contentScope, this trackAndClose function would be in the wrong place (my courses list controller) instead of in my NewCourseCtrl I'd like to use when instantiating the modal.

@lunks
Copy link

lunks commented Sep 10, 2015

I've created a PR for this, see #689

@AliAkbarLatifi
Copy link

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Development

No branches or pull requests

5 participants