0

I'm new to the AngularJS world and come from a Backbone background. So far I'm loving it but there is quite a big difference in terms of architecture practices between the two ( someone should write an article on this lol ).

I'm starting to structure some quite large controllers and it just doesn't feel right. For instance, this is a basic control that deals with executing a search and populating the ng-grid control and infinite scrolling this grid.

var ctrl = ['$scope', 'model', '$modal', function ($scope, model, $modal) {

    $scope.page = 0;
    $scope.loading = true;
    $scope.mySelections = [];
    $scope.rows = [];
    $scope.columnDefs = [{
        field: 'Checked',
        width: "50",
        sortable: false,
        headerCellTemplate: '<input class="ngSelectionHeader" type="checkbox" ng-show="multiSelect" ng-model="allSelected" ng-change="toggleSelectAll(allSelected)"/>',
        cellTemplate: '<div class="ngSelectionCell"><input tabindex="-1" class="ngSelectionCheckbox" type="checkbox" ng-checked="row.selected" /></div>'
    }];
    $scope.gridOptions = {
        data: 'rows',
        columnDefs: "columnDefs",
        enableColumnResize: true,
        selectedItems: $scope.mySelections,
    };

    /**
     * Pages the grid and returns a $.deferred
     */
    var pageGrid = function () {
        return model.ExecuteSearchForReport("4146", ++$scope.page)
            .done(function (records) {
                $.each(records, function (i, record) {
                    var fields = {};
                    $.each(record.Value, function (ii, field) {
                        var fieldKey = field.Key.replace(/\s/g, '');
                        fields[fieldKey] = field.Value;
                    });

                    $scope.rows.push(fields)
                });
                $scope.$digest();
            });
    };

    /**
     * Page the grid initally.
     */
    pageGrid().done(function (records) {
        createColumns(records);
        $scope.loading = false;

        // if the grid height 
        var gridHeight = $('.ngGrid').height();
        var repage = function () {
            if ($('.ngCanvas').height() < gridHeight) {
                pageGrid().done(function () {
                    repage();
                });
            }
        };
        repage();

        $scope.$digest();
    });

    /**
     * Creates the columns for the grid based on the records.
     */
    var createColumns = function (records) {
        if (records.length) {
            $.each(records[0].Value, function (ii, field) {
                var fieldKey = field.Key.replace(/\s/g, '');

                var col = {
                    field: fieldKey,
                    displayName: field.Key,
                    resizable: true
                };

                // all the other columns are small
                if (fieldKey !== "FileName") {
                    col.width = "100";
                }

                $scope.columnDefs.push(col);
            });
        }
    };

    /**
     * List for `ngGridEventScroll` event to page the data set.
     */
    $scope.$on('ngGridEventScroll', function () {
        pageGrid();
    });

    /**
     * Move the secure button was clicked, load next screen.
     */
    $scope.moveToSecure = function () {
        $scope.loading = true;

        model.GetSecureDetails().done(function (data) {
            $scope.loading = false;

            var modalInstance = $modal.open({
                templateUrl: 'Views/Modal.html',
                controller: ModalInstanceCtrl,
                resolve: {
                    data: function(){
                        return {
                            header: "Move To Secure",
                            body: "Views/Move.html",
                            lists: data
                        };
                    }
                }
            });

            modalInstance.result.then(function (formData) {
                var defs = [];
                $.each($scope.mySelections, function (i, sel) {
                    defs.push(model.MoveToSecure({
                        Id: sel.EventID.substring(4, sel.EventID.length),
                        Filename: sel.FileName
                    }));
                });

                $.when.apply($, defs).done(function () {
                    alert('Move completed');
                });
            });
        });
    };
}];

I know, its a lot and it feels unstructured somewhat to me, between all the variable initialization, private methods, and general initialization methods. It doesn't feel concise and deterministic to me, which is something I liked about Backbone. Anyone got any feedback on a better way to do this? Thanks!

2
  • Have you gone through the AngularJS tutorial? If not, do. If yes, then you should just start with the sample project from the tutorial and just modify it to fit your needs. The reason for that is that it will show you how to organize your GIANT controller into different modules using services, factories and directives. Or you can use the seed project found here Commented Oct 16, 2013 at 20:37
  • PS. Here's a nice article from a Backbone guy that explains how to start in Angular from a backbone perspective: blog.appfog.com/angularjs-the-beauty-of-concision Commented Oct 16, 2013 at 20:40

1 Answer 1

3

You need to move most of that stuff into 'concise' directives. If you don't master directives, your controllers will always end up overburdened and crazy like this. Ideally your controller pretty much only takes data back and forth between your scope and services.

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

Comments

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.