Search code examples
javascriptangularjsangularjs-material

Update ng-repeat after Angular Material dialog data entry / push


I'm trying to add a new object to an ng-repeat array. The array is created with data acquired through an $http request. I need to be able to pass data that I've entered in a dialog to a function that then pushes this data, as an object, onto the array and updates the view. I can log the values of the inputs in the console just fine and even when I log the array it will show the updated values but it won't update the view. Also, it will update the array if I add an object with a button that is not in the dialog.

UPDATE

After viewing the scopes overview with Chrome's Angular ng-Inspector, I can see that the new object is being added to the array within the scope of the controller which is a parent of the element where the ng-repeat takes place. The element where the ng-repeat takes place has its own scope and I can see that the array is not being updated there. I need this array to be the one that is updated since that is where the ng-repeat is and that is what is being viewed. I'm still a little confused by how there can be two of the same array where one changes while the other doesn't. When I push the object onto '$scope.plots' I need to target the scope of the ng-repeat parent element. I still haven't found a good way to do this.

Here is my dialog

function showAdd(ev) {
        $mdDialog
            .show({
                controller: DialogController,
                templateUrl: '/templates/addDialog.html', //contains inputs that are modeled to values as seen in the push function below. A button calls addPlant()
                targetEvent: ev,
                clickOutsideToClose: true,
                openFrom: 'left'
            }).then(function(added) {
                newPlant(added);
        })
    }

Here is my dialog controller

function DialogController($scope, $mdDialog, $http) {
$scope.addPlant = function (added) {
    for (var i = 0; i < added.quantity; i++) {
        $http.post('/addPlant', added).then(function () { //this is just posting the data to a database, not related to the issue.
                $mdDialog.hide(added);
            }
        });
    }
};

And the push function

var newPlant = function(added) {
        $scope.plots.push({
            'plot': added.plot,
            'varieties': [{
                'count': added.quantity,
                'variety': added.variety
            }],
            'count': added.quantity
        });

Solution

  • I ended up having to create a service and broadcast the added object from the rootScope. I created a separate controller for the ng-repeat element that listened for the broadcast.

    When the dialog is closed it resolves the promise passing the form data to the service.

    $mdDialog
            .show({
                controller: 'DialogCtrl as dc',
                templateUrl: '/templates/addDialog.html',
                targetEvent: ev,
                clickOutsideToClose: true,
                openFrom: 'left'
            }).then(function(added) {
                addPlant.prepForBroadcast(added) //calling service in promise, passing 'added' input values
        })
    

    I created a service to broadcast the object

    var myApp= angular.module('myApp');
    
    myApp.factory('addPlant', ['$rootScope', function($rootScope) {
        var box= {}; //I like to call the designated factory object a 'box'
        box.newPlant = {};
    
        box.prepForBroadcast = function(added) {
            box.newPlant = added;
                this.broadcastItem();
        };
    
        box.broadcastItem = function() {
            $rootScope.$broadcast('broadcast');
        };
        return box; //ship out the box with the newPlant
    }]);
    

    And a separate controller for the ng-repeat element, listening for broadcast

    myApp.controller('ListCtrl', ['$scope','addPlant', function($scope, addPlant) {
    
    $scope.$on('broadcast', function() { //listening for broadcast
            $scope.plots.push({
                'plot': addPlant.newPlant.plot,
                'count': addPlant.newPlant.quantity,
                'varieties': [{
                    'variety': addPlant.newPlant.variety,
                    'count': addPlant.newPlant.quantity
                }]
            });
        })
    }]);