44

I figured if I slapped ng-controller="GeneralInfoCtrl" on multiple elements in my DOM they would share the same $scope (or least two-way binding isn't working).

The reason I want to do this is because I have different read-only views with associated modal dialogs in very different parts of the HTML and they don't share a common ancestor (aside from <body> and <html>).

Is there a way to make both controllers refer to the same object/make data binding work between them?


Here's some code for those who insist on seeing markup, written in Jade:

   .client-box(ng-controller="GeneralInfoCtrl")
        .box-header
            .box-title
                h5 General Information
            .box-buttons
                button.btn.btn-small(data-target='#editGeneralInfo', data-toggle='modal', data-backdrop='static') <i class="icon-pencil"></i> Edit
        .box-body
            table.table.table-tight.table-key-value
                tr
                    th Name
                    td {{client.fullName()}}
                tr
                    th Also Known As
                    td {{client.aka}}
                tr
                    th Birth Date
                    td {{client.birthDate|date:'mediumDate'}}
    ...

#editGeneralInfo.modal.hide.fade(ng-controller="GeneralInfoCtrl")
    .modal-header
        button.close(type='button', data-dismiss='modal') &times;
        h3 Edit General Information
    .modal-body
        form.form-horizontal.form-condensed
            .control-group
                label.control-label First Name
                .controls
                    input(type='text', placeholder='First Name', ng-model='client.firstName')
            .control-group
                label.control-label Last Name
                .controls
                    input(type='text', placeholder='Last Name', ng-model='client.lastName')
            .control-group
                label.control-label Also Known As
                .controls
                    input(type='text', placeholder='AKA', ng-model='client.aka')
            .control-group
                label.control-label Birth Date
                .controls
                    input(type='text', placeholder='MM/DD/YYYY', ng-model='client.birthDate')
...

And my controller:

function GeneralInfoCtrl($scope) {
    $scope.client = {
        firstName: 'Charlie',
        lastName: 'Brown',
        birthDate: new Date(2009, 12, 15),
        ...
    }
}
mpen
  • 272,448
  • 266
  • 850
  • 1,236

2 Answers2

76

Each time the Angular compiler finds ng-controller in the HTML, a new scope is created. (If you use ng-view, each time you go to a different route, a new scope is created too.)

If you need to share data between controllers, normally a service is your best option. Put the shared data into the service, and inject the service into the controller:

function GeneralInfoCtrl($scope, MyService) {

Each scope/controller instance will then be able to access the shared data.

Note that services are singletons, so there will only be one instance of your shared data around.

Here is a fiddle (I didn't write it) showing how two controllers can share data.

See also AngularJS: How can I pass variables between controllers? and
Angularjs: two way data bindings and controller reload.

Community
  • 1
  • 1
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
13

Simply put shared data in the root scope, you'll be able to use them everywhere. In Angular $rootScope is the root of all scopes and can be used in controllers to manage data that must be visible across all modules. To use it just inject it in the controller function. For a detailed explanation refer to the Angular developer's guide and to the API doc.

remigio
  • 4,101
  • 1
  • 26
  • 28
  • Thank you. Couldn't find mention of `$rootScope` in the developer guide, but it's in the API. Is this really the best approach? I don't need access in other "modules", just inside this one controller. – mpen Jan 22 '13 at 07:36
  • Also, suppose that I did want to have multiple clients one page, and clicking a certain "edit" button beside one of them would use the controller/scope for that client rather than a global/shared one... what then? Perhaps I need to do some more reading... – mpen Jan 22 '13 at 07:42
  • 1
    You can have multiple controllers, each with its own separate scope, in the same page. If your need to share data isn't occasional you should think about using "services". Read the "Using Controllers Correctly" section in [the developer's guide](http://docs.angularjs.org/guide/dev_guide.mvc.understanding_controller). – remigio Jan 22 '13 at 07:46