4

I need help with this code can someone please suggest what must I do to bring the names of contacts in the table on page load. What I have done is I saw this

http://www.saaspie.com/2015/03/27/developing-simple-application-in-salesforce-using-angular-js/

and implemented Angular JS from there and then replaced the code for fetching contacts list using remote actions. I am getting the contacts array in a variable that is declared out of scope but not loading on page as I want

my page code is

<apex:page controller ="SampleRemoteActionWithAngularJS" standardStylesheets="false" applyHtmlTag="false" sideBar="false" showHeader="false">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js">
</script>
<script>
var app = angular.module('MyApp',[]);
var mytestvar;
app.controller('myController',['$scope',function($scope)
{
$scope.ctdata;
$scope.ContactData =  Visualforce.remoting.Manager.invokeAction(
        '{!$RemoteAction.SampleRemoteActionWithAngularJS.getContacts}',
         function(result, event) 
         {
            console.log(result);
            $scope.ctdata = result;
            mytestvar = result;

         }); 
      }]);
</script>
<div ng-app="MyApp">

<div ng-controller="myController">
<table>
<thead>
<th>
Name
</th>
</thead>
<tr ng-repeat="Contactvar in ctdata">
<td>{{Contactvar.Name}}</td>
</tr>
<tbody >
</tbody>
</table>
<button onclick ="alert(JSON.stringify(mytestvar))">Show Alert !!!</button>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
</apex:page>

and apex code is

public with sharing class SampleRemoteActionWithAngularJS {

    @RemoteAction
    public static list<contact> getContacts()
    {
        return [SELECT Id, Name FROM contact limit 10];
    }
}

Please help I want to learn this

3 Answers 3

3

Short answer: you need to use $scope.$apply to force angularJs to reload the elements. So your code should look like this:

$scope.ContactData =  Visualforce.remoting.Manager.invokeAction(
        '{!$RemoteAction.SampleRemoteActionWithAngularJS.getContacts}',
         function(result, event) 
         {
            $scope.$apply(function() {
              console.log(result);
              $scope.ctdata = result;
              mytestvar = result;
            });
         }); 
      }]);

The longer answer: AngularJS watches all the elements in the watchList. It gets updated every time it notices anything has changed in the watchList. It knows the things changed by subscribing itself to all the regular angular methods so usually it updates automatically. Even during ajax callback methods, if you use the angular way of doing it, it is still fine.

But the exception is none-angular methods. Javascript remoting is definitely one example. So you need to manually notify angularJs to reRender the page in the callBack function. In this case, use $scope.$apply.

Note: AngularJS might seem to be easy in the first instance, but it is not as easy when you try to master it... It is like marriage. If you are just into the template engine and small stuffs like sorting, filtering, etc.(Like I did) Consider using a template engine and a lightweight sorting js library, not the whole monolithic AngularJS.

1

Your code is absolutely fine the only problem is it is not correctly binding that with page once data return from remote action. so you need to add $scope.$apply(); which will bind explicitly after getting the data from the remote action response.

your function will look like this.

function(result, event) 
{
            console.log(result);
            $scope.ctdata = result;
            mytestvar = result;
            $scope.$apply();
}); 
1

The other two answers are correct in principle, but there is a better way to tell angular that that something has updated - $scope.$applyAsync().

This prevents "digest already in progress" errors that you are likely to occur if you just call scope.apply(). Also, it's more efficient to use applyAsync() as just queues up the function that you feed it and will call it in the next digest cycle.

Your code could look like this:

function(result, event) 
{
    $scope.applyAsync(function(){
        $scope.ctdata = result;
        mytestvar = result;
    });
}); 

You must log in to answer this question.

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