madhead
madhead

Reputation: 33511

How to manage data between Angular scopes?

I have such markup:

<ul>
    <li data-ng-controller="TileController">
        <h1>Title</h1>
        <span>
            <a href="#" data-ng-click="loadBeanForEdit()">
        </span>
        ....
        <div id="beanEditModal" data-ng-controller="TileBeanController">
            <!-- Bootstrap modal -->
        </div>
    </li>
    <li>
        ...
    </li>
    ...
</ul>

Workflow is: user clicks a and I want to load some data with ajax to edit it in popup:

function TileController($scope) {
    $scope.loadBeanForEdit= function(e) {
        e.stopPropagation();
        $("#beanEditModal").modal();
    };
}

The problem is that I do not want to keep data in parent scope (TileController) I want to load it into TileBeanController scope. But how can I do it from parent controller? Or, maybe there is better approach?

Upvotes: 2

Views: 185

Answers (2)

F Lekschas
F Lekschas

Reputation: 12820

In general you need to create a service so that your two controllers can communicate. What I would do is to extent the loadBeanForEdit function like so

function TileController($scope, News) {
    $scope.loadBeanForEdit= function(e) {
        e.stopPropagation();
        News.setModal(some-id-or-whatever);
        $("#beanEditModal").modal();
    };
}

So this function calls a service which informs everyone who is listening that the modal has been opened. Your service could look something like this:

angular.factory('News', function($rootScope) {
    var news = {};

    // Sets and broadcasts that a modal has been opened
    news.setModal = function( id ) {
        this.modal = id;
        $rootScope.$broadcast('modal');
    };
});

All you need to do now is to listen to when something is broadcasted within your TileBeanController like so:

function TileBeanController($scope, News) {
    $scope.$on('modal', function() {
        // Load data
    });
}

I hope that helps :)

Upvotes: 4

Eugenio Cuevas
Eugenio Cuevas

Reputation: 11078

If you require an scope for your element, I would wrap it on a directive with isolated scope:

myApp.directive('tilebean', function () {
    return {
        restrict : 'E',
        scope: {
            data: '='
        },
        template: '<div id="beanEditModal"><!-- Bootstrap modal -->This is your title: {{data.title}}</div>'
    };
});

You can then bind this data parameter in the view:

<ul>
    <li data-ng-controller="TileController">
        <h1>Title</h1>
        <span>
            <a href="#" data-ng-click="loadBeanForEdit()">
        </span>
        ....
        <tilebean ng-model="data"></tilebean>
    </li>
    <li>
        ...
    </li>
    ...
</ul>

And populate the data in the controller:

function TileController($scope) {
    $scope.loadBeanForEdit= function(e) {
        e.stopPropagation();
        $("#beanEditModal").modal();
        $scope.data = getDataFromAjax();//replace this for your ajax call
    };
}

Upvotes: 3

Related Questions