简体   繁体   中英

AngularJS - How to run controllers from other controllers?

I'm new to angular, coming from a jquery way of thinking. I've read through most of the main site and bits of others, and I'm trying to further learn by building a customizable dashboard application.

My HTML:

    <div class="library">
        <div class="dropdown" ng-controller="LibraryCtrl">
            <div id="lib-{{widget.WidgetID}}" ng-repeat="widget in widgets">
                <div data-toggle="tooltip" title="{{widget.WidgetDesc}}">
                    <h2>
                        {{widget.WidgetName}}</h2>
                    <div class="libraryWidget {{widget.WidgetReportType}}">
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="dashboard" ng-controller="DashboardCtrl">
        <div>
            <article>
                <div id="dash-{{widget.WidgetID}}" class="jarviswidget" ng-repeat="widget in widgets">
                    <header role="heading">
                        <h2>
                            {{widget.WidgetName}}</h2>
                    </header>
                    <div role="content" class="content">
                        <div class="inner-spacer">
                            <div class="table">
                            </div>
                        </div>
                    </div>
                </div>
            </article>
        </div>
    </div>

Essentially, I am building one view for the "library" of available widgets, and another view for the widgets currently picked for their "dashboard". The HTML is still pretty simple here. The library view renders just fine, but the dashboard view does not.

The JavaScript:

function LibraryCtrl($scope, $http, sharedModels) {
    $http({
        method: 'POST',
        url: '../Services/GetUserWidgetDetails',
        headers: {
            'Content-type': 'application/json'
        }
    }).success(function (data) {
        sharedModels.setProperty(data);
        $scope.widgets = data;
        console.log(data); // logs 2nd with expected data
    });
}

function DashboardCtrl($scope, sharedModels) {
    var libraryWidgets = sharedModels.getProperty();
    $scope.widgets = libraryWidgets;
    console.log(libraryWidgets); // logs 1st with empty object
}

angular.module('dashboard', [])
    .service('sharedModels', function () {
        var libraryModel = {};

        return {
            getProperty: function () {
                return libraryModel;
            },
            setProperty: function (data) {
                libraryModel = data;
            }
        };
    });

Both of my controllers ought to use the same model, so at the suggestion of other SO posts I've created the service to get and set this shared model. The problem is, my DashboardCtrl tries to render its view before the success of LibraryCtrl. What would be the angular way of solving this problem: making DashboardCtrl wait for LibraryCtrl's success?

Further, (and this may be deserving of being its own question/post,) if the div.content element in my div.dashboard view is going to one of many possible sub-templates depending on LibraryCtrl's success JSON, how might I go about doing this? In jquery templating, I would have id's for each template, and jquery would render the HTML and append it where needed. In angular, I'm not sure exactly how to pick a template and render inside of another template. This need not be spelled out for me quite like my first bolded question above, but a point in the right direction would be great!

To your first question : Instead of loading the data in LibraryCtrl and using it in DashboardCtrl , create a service. Load the model via the service and have both controllers use it.

http://docs.angularjs.org/api/ngResource .$resource

If you haven't looked at angular-seed , take a peek at it. It gives a good skeleton for this sort of thing.

To your second question : This is an ideal place for directives. (The answer to a vast number of Angular questions is 'make a directive', and that's doubly so if you're making reusable widgets). In fact, I'd do a directive for the dashboard as a whole, and another for 'dashboard-item'. Rather than specifying the template directly in the directive declaration, use templateUrl...which can use the result of an expression. Point it at different template files depending on the type.

Alternatively, create one template file and use ng-switch based on type to determine which section of it to display.

For info on creating directives, look at the tutorial and also look here .

Skip down to "Writing directives (long version)". Don't read the compilation and linking stuff yet; go back to it if you need it. The order in which stuff is presented on that page is unfortunate.

Move the loading of the data into the service, and then use the service in both controllers:

http://jsfiddle.net/ADukg/2631/

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

function LibraryCtrl($scope, sharedModels) {
    $scope.widgets = sharedModels;
}

function DashboardCtrl($scope, sharedModels) {
    $scope.widgets = sharedModels;
    sharedModels.then(function (x) {
        console.log(x); 
    });
}

myApp.factory('sharedModels', function($q,$timeout) {
    /*
    return $http({
        method: 'POST',
        url: '../Services/GetUserWidgetDetails',
        headers: {
            'Content-type': 'application/json'
        }
    })*/
    // Simulate http request.
    var data = $q.defer();    
    $timeout(function() {
        data.resolve([{WidgetName:'Sproket'}, {WidgetName:'Dohickey'}])
    }, 2000);
    return data.promise;
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM