3

I am trying to do a simple remoting code base along with auto update to angular table. BUt if I call a remote method as it is async, it gets called late and even though I try to push data in my angular table, it does not render the view correctly.

VF page code (check method addrow)

<apex:page standardStylesheets="false" sidebar="false" showHeader="false" controller="Angular_HelloWorld">
    <style>
        table, th , td  {
            border: 1px solid grey;
            border-collapse: collapse;
            padding: 5px;
        }
    </style>
    <html  ng-app="myApp">
        <link rel="stylesheet" href = "https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
        <script src= "https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>

        <body>

        <div ng-controller="personCtrl">
            Search table :<br/>
            <input type="text" ng-model="criteria" /> <br/><br/>
            <table class="table table-striped table-bordered table-hover table-condensed">
                <thead>
                    <tr>
                        <th>Id</th>
                        <th>Name</th>
                        <th>Phone</th>
                    </tr>
                </thead>
                <tr ng-repeat="x in contacts | filter:criteria">
                    <td>{{x.id}}</td>
                    <td>{{x.name}}</td>
                    <td>{{x.phone}}</td>
                </tr>
            </table>

                <form name="myForm">
                    First Name :<br/>
                    <input type="text" ng-model="firstName"/><br/>
                    Last Name :<br/>
                    <input type="text" ng-model="lastName" />
                    <br/>
                    Phone :<br/>
                    <input type="text" ng-model="phone" /><br/>
                    <br/>
                    <button ng-click="addRow();" >Add</button>
                </form>
        </div>
        <script>
            angular.module('myApp', []).controller('personCtrl', function($scope, $http) {
                $scope.fullName = function() {
                    return $scope.firstName + ' ' + $scope.lastName;
                };

                var response =
                    JSON.parse('{"records": [{"Name": "John Doe","City": "Berlin","Country": "Germany"},{"Name": "Robert","City": "Mumbai","Country": "India"}]}');
                $scope.names = response.records;
                $scope.contacts = {!contactListJSON};

                $scope.reset = function() {
                    delete $scope.firstName;
                    delete $scope.lastName;
                    delete $scope.phone;
                }

                $scope.addRow = function() {
                    var contactJS = new Contact();
                    contactJS.firstName = $scope.firstName;
                    contactJS.lastName = $scope.lastName;
                    contactJS.phone = $scope.phone;
                    Visualforce.remoting.Manager.invokeAction(
                        '{!$RemoteAction.Angular_HelloWorld.insertContact}',
                        contactJS,
                        function(result, event) {
                            console.log('result', result);
                            $scope.contacts.push({result});
                        },
                        {escape:false}
                    );
                    $scope.reset();
                }

                function Contact() {
                    this.id = null;
                    this.lastName = null;
                }
            });

        </script>
        </body>
    </html>

</apex:page>

Controller method (check insertContact method)

public class Angular_HelloWorld {
    public static String getContactListJSON() {
        List<ContactWrapper> contactWrapper = new List<ContactWrapper>();
        for (Contact contactInstance : [SELECT Id, Name, Phone FROM Contact ORDER BY CreatedDate LIMIT 5]) {
            contactWrapper.add(
                new ContactWrapper(
                    contactInstance.Name,
                    contactInstance.Id,
                    contactInstance.Phone
                )
            );
        }
        return JSON.serialize(contactWrapper);
    } 

    @RemoteAction
    public static String insertContact(Contact contaceInstance) {
        insert contaceInstance;

        return JSON.serialize(
            new ContactWrapper(
                contaceInstance.Name,
                contaceInstance.Id,
                contaceInstance.phone
            )
        );
    }

    public class ContactWrapper {
        public String name;
        public String id;
        public String phone;
        public ContactWrapper(String name, String id, String phone) {
            this.name = name;
            this.id = id;
            this.phone = phone;
        }
    }
}

but when I call remoting on page and then this line -

$scope.contacts.push({result});

It does not work and latest data is not pushed to table.

Any help???

Thanks, Ray

2
  • Try $scope.contacts.push(result);. But your browser's JavaScript console and debugger are the basic tools you need to learn to do this sort of work.
    – Keith C
    Sep 28, 2015 at 19:13
  • @KeithC, already tried same along with other options like returning direct contact instance, $scope.contacts.push(result);, $scope.contacts.push({result});, and even $scope.contacts.push({name:$scope.firstName, phone:$scope.phone}); This works properly when out of remoting context but not when inside remoting context
    – SEuser
    Sep 28, 2015 at 19:18

1 Answer 1

1

Typically with angular, when you make asynchronous calls, you need to work with promises (documentation). In practice, this works like:

$scope.callRemoteMethod = function () {
    var deferred = $q.defer();
    myRemotemethod(params, function (result, event) {
        if (event.status) {
            deferred.resolve(result, event);
        }
    });
    deferred.promise.then(function (result, event) {
        // now do stuff
    });
}

You can add reject logic as well if you like, but you can dive pretty deep into promises and that falls somewhat outside the scope of this question.

7
  • Is this a specific angular version method. I am using 1.3.15
    – SEuser
    Sep 28, 2015 at 19:49
  • on my version, I tried $scope.$digest(); which reflected the changes on my array, but the concept of promise looks promising :), not sure if available on older versions
    – SEuser
    Sep 28, 2015 at 19:52
  • and as per docs, resolve will take single param of value? not both result and event?
    – SEuser
    Sep 28, 2015 at 19:53
  • According to the docs, it looks like $q has been supported since 1.2.14.
    – Adrian Larson
    Sep 28, 2015 at 19:58
  • AFAIK resolve just calls the successCallback on your promise, which you can define yourself as I do above with deferred.promise.then.
    – Adrian Larson
    Sep 28, 2015 at 19:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .