3

I have an AngularJS application that I believe is essentially pretty typical (alike many of the examples).

<html ng-app="myApp" ...
<body>
...
    <div class="main" ng-view></div>
    ...

There's a $routeProvider that I've set up with a whole lot of whens to direct users to a view (template partial with a controller), such as:

$routeProvider.when('/incident/:identifier', {templateUrl:'incident.html', controller:"IncidentCtrl"});

This is all working fine. Users can go back and forth between views.

Now, let's say I have a view for an "incident". It has a form with properties of the "incident". (You can change values in the form and "Save", which is besides the point here.) I have the following requirements:

  1. "Add work order" button below the existing form
  2. When button clicked, a form (partial) is loaded below the existing form to enter details for a new "work order"
  3. "Save" button as part of the loaded form (partial) will save the new "work order"
  4. The form (partial) is closed, unloaded or at least visually removed
  5. Possibly go back to 2. to repeat (to add subsequent "work orders")

For the form that is loaded below the existing form I would like to reuse an existing template partial with its subsequent controller, which I'm already using for the top-level ng-view elsewhere. But I've gone down a few roads to implement this at no avail; ng-include seems to not work, as it is pretty static and does not allow for much of a lifecycle on the embedded element. Also, it seems hard to load it dynamically, which means it's gonna be loaded before the "Add work order" button is ever clicked. Could someone point me to a workable strategy? Clearly my goal is to promote reuse of existing template partial and controller, without always having the user to move between views. Much appreciated.


Edit: elaborating: I'm not happy (yet) with any ng-include ideas that I've seen so far, since:

  • There would be a bunch of them if I had more than just a single kind of view to embed. They would all get loaded ahead of being shown for no good reason; overkill
  • I do not know how to parameterize the embedded views in the same way I can pass $routeParams from the $routeProvider
  • I am uncomfortable of too much sharing between parent and child scopes
  • I have no way to cleanly recreate the controller for subsequent "adds"
5
  • 1
    Not sure what you meant from the last paragraph, but ng-include should work. What issue are you facing with using ng-include. Commented Sep 24, 2013 at 16:41
  • 2
    You might want to look into using ui-router, it allows nesting views. Commented Sep 24, 2013 at 18:52
  • @Chandermani I have added some objections against ng-include to the question and below Beteraba's answer. Commented Sep 25, 2013 at 4:20
  • @Jakemmarsh I've checked out the link to ui-router and it looks very promising. I'll spend a spike on that :) Commented Sep 25, 2013 at 4:21
  • @Jakemmarsh I've looked some more into ui-router and I believe that is the way forward for my application. If you post an answer, I'm happy to accept it. Commented Sep 25, 2013 at 9:16

2 Answers 2

5

I would try to address your concerns with ng-include

There would be a bunch of them if I had more than just a single kind of view to embed. They would all get loaded ahead of being shown for no good reason; overkill

ng-if can help you here. This directive would not load DOM till the condition becomes true. And it also destroys the DOM when the condition becomes false. So something like

    <div ng-if='conditionwhenthepartialshouldbeshown'>
      <ng-include src='templateName'  ng-init='model=parent.someProperty'/>
    </div>

I do not know how to parameterize the embedded views in the same way I can pass $routeParams from the $routeProvider

You can use ng-init for passing some parameters when the view is loaded. Check documentation

I am uncomfortable of too much sharing between parent and child scopes

ng-init can help here again. You can create a property on child scope and pass it the parent scope value in ng-init

I have no way to cleanly recreate the controller for subsequent "adds"

ng-if does this for you.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for that. This looks like useful and relevant information, I've upvoted you. But I'm likely to go with ui-router as a solution. After spending some time on it, I believe that is the way forward for my application.
Yes ui-router would be better, as it has been targeted at nested views, but what i have shared here would still come in handly :)
2

The way that I found to reproduce this behavior was using Two controllers: One for your "main" view and one for your partial view.

In your controllers file

var controllers = angular.module('controllers', []);

controllers.controller('IncidentCtrl', ['$scope', function($scope) {
    // Incident Ctrl Body
    $scope.showForm = false;
    $scope.toggleForm = function() {
        $scope.showForm = !$scope.showForm;
    }
}]);

controllers.controller('WorkOrderCtrl', ['$scope', function($scope) {
    // Partial Form controller
    // This controller can talk with $scope from IncidentCtrl 
    //    using the $scope.$parent.$parent

    $scope.save = function() {
        // ...
        $scope.$parent.$parent.showForm = false;
    }
}]);

And your views:

<!-- incident.html -->
<button data-ng-click="toogleForm()"> Toggle Form </button>
<div data-ng-show="showForm">
    <div ng-include src="'path/to/_work_order.html'"></div>
</div>

<!-- _work_order.html -->
<div data-ng-controller="WorkOrderCtrl">
   <!-- view body -->
   <button data-ng-click="save()"> Save </button>
</div>

3 Comments

Thank you for this. I have to try this out and respond on basis of that, so the following is premature perhaps. But how do you deal with lifecycle? Normally the partial would be initialized emtpy when the user goes to a certain view (as would the controller be constructed freshly and thus initialize all variables). Here you would "Save", hide the form, and if you ever "Add" another one end up being right back were you took off (with the "Save"). Perhaps I was hoping for a little more control on that.
Thank you again for this. I have added a few objections to the question for the ng-include approach as I've seen it so far.
I believe that your objections are answered by Chandermani and Jakemmarsh.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.