‘Cannot read property '...controller' of undefined’ remote call to Salsforce Controller through angular Js Controller

788 views
Skip to first unread message

Sun Nathan

unread,
Oct 18, 2013, 3:14:53 PM10/18/13
to ang...@googlegroups.com

Hello All,

We are using anuglar js on salesforce app. We are getting exception  : Cannot read property 'bhatindexcontroller' of undefined , Can some one help?

‘Cannot read property 'bhatindexcontroller' of undefined’ exception occurs on remote call through angular Js Controller ( Remoting invokeAction through angular js)

Calling Code:

bhatModule.

factory('getActivityList', ['$q', '$rootScope', function ($q, $rootScope) {



    return function (inputString) {



       var deferred = $q.defer();



        Visualforce.remoting.Manager.invokeAction(

            '{!$RemoteAction.bhatindexcontroller.getActivityList}',

            inputString,

            function (result, event) {

                $rootScope.$apply(function () {

                    if (event.status) {

                        deferred.resolve(result);

                    } else {

                        deferred.reject(event);

                    }

                })

            },

            { buffer: true, escape: true, timeout: 30000 }

        );



        return deferred.promise;

    }



}]);

Error:

TypeError: Cannot read property 'bhatindexcontroller' of undefined at Object.$VFRM.Util.getObject (https://c.na15.visual.force.com/jslibrary/1381859968000/sfdc/VFRemote.js:119:364) at $VFRM.ProviderManager.VFExt3.extend.getController (https://c.na15.visual.force.com/jslibrary/1381859968000/sfdc/VFRemote.js:134:91) at $VFRM.ProviderManager.VFExt3.extend.getAction (https://c.na15.visual.force.com/jslibrary/1381859968000/sfdc/VFRemote.js:134:472) at $VFRM.ProviderManager.VFExt3.extend.invokeAction (https://c.na15.visual.force.com/jslibrary/1381859968000/sfdc/VFRemote.js:135:364) at https://c.na15.visual.force.com/resource/1382075777000/bhatremotingjs:38:42 at new (https://c.na15.visual.force.com/resource/1382075777000/bhatcontrollersjs:46:3) at invoke (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js:2864:28) at Object.instantiate (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js:2874:23) at https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js:4759:24 at update (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js:14114:26)

Here are the code snippets:

Index Page (VF): Bhatindex

<meta http-equiv="PRAGMA" content="NO-CACHE" />

<meta http-equiv="Expires" content="Mon, 01 Jan 1990 12:00:00 GMT" />

<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" name="viewport" />

<style>

    body

    {

        padding-top: 125px; /* 60px to make the container go all the way to the bottom of the topbar */

    }



    .button

    {

        text-align: center;

    }

</style>



<style>

    .red

    {

        color: red;

    }



    .black

    {

        color: black;

    }



    .green

    {

        color: #35d648;

    }

</style>







<link href="{!URLFOR($Resource.Bhat_Resources_AngularJS, 'resources/css/custom.css')}" rel="stylesheet" />





<link href="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap.css" rel="stylesheet" />

<link href="{!URLFOR($Resource.Bhat_Resources_AngularJS, 'resources/css/bhatdefault.css')}" rel="stylesheet" />







<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>







<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js"></script>

<!-- Local Static Resource css and javascript, all part of Angular-Seed app. -->

<script src="{!URLFOR($Resource.bhatcontrollersjs)}"></script>

<script src="{!URLFOR($Resource.bhatdirectivesjs)}"></script>

<script src="{!URLFOR($Resource.bhatfiltersjs)}"></script>

<script src="{!URLFOR($Resource.bhatservicesjs)}"></script>

<script src="{!URLFOR($Resource.bhatappjs)}"></script>

<script src="{!URLFOR($Resource.bhatremotingjs)}"></script>

<div id="simplyDoBanner"  class="hidden-phone">

   <table border="0" cellpadding="0" cellspacing="0">

   <tbody>

        <tr>

            <td class="left">

                <div style="height: 70px;">







                    <img src="{!URLFOR($Resource.Bhat_Resources_AngularJS, 'resources/img/locals2011_01.jpg')}"

                        alt="Powered by S.O.S"

                        title="Powered by S.O.S" / ></div>

            </td>

            <td align="right" style="text-align:right;">



                    <div>



                   <span style="color:#F7F7F7;font-size:20px;">Activity Tracker</span>

                   </div>

            </td>

            <td></td>

        </tr>

     </tbody>  

    </table>

 </div>











<div class="container">

    <div class="ngView">

    </div>

</div>







<div id="footer"  class="hidden-phone">

    <div class="container">

        <div class="row">

            <div class="span4">

                <p>

                    &copy; 2013 <a target="new" href="http://strategicorganizingsystems.com">S.O.S</a>, LLC.<br/>

                    All Rights Reserved.</p>

            </div>



        </div>

    </div>

</div>

/apex:page

VF Controller : BhatindexController

global with sharing class bhatindexcontroller {

public class MyException extends Exception {}

// VF Remoting method.
// Double the string value passed, where double means:
//   if integer, multiple reslt by 2.
//   if exact string "exception", throw an exception event (to demonstrate an exception in VF Remoting).
//   if any other string, double each character.
@RemoteAction
global static  string valueDoubler(String inputValue) {
    String result = '';

    if (inputValue == 'exception')
        throw new MyException('Forced Exception');

    if (inputValue.isNumeric())
        result = String.valueOf(Integer.valueOf(inputValue) * 2);
    else
        for (Integer i=0; i<inputValue.length(); i++)
            result += inputValue.mid(i,1) + inputValue.mid(i,1);

    return result;
}


@RemoteAction
global  static string getActivityList(String inputValue) {

List < Activitywrap > lstwrap = new List < Activitywrap > ();

  try {


      List < BHAT_Activity_Daily__c> lstacc = [SELECT Activity_Date__c, Daily_Hours_Spent__c 
                                 FROM BHAT_Activity_Daily__c limit 100
                                ];

  system.debug('Sun 2013 - read activity')    ;                              
      for (BHAT_Activity_Daily__c a: lstacc) {
          Activitywrap awrap = new Activitywrap ();
          awrap.ActivityDate = a.Activity_Date__c;
          awrap.DailyHoursSpent = a.Daily_Hours_Spent__c;

          lstwrap.add(awrap);
      }

      system.debug('Sun 2013 - wrapped object');

} catch(Exception e) {

  system.debug('Sun 2013 - Error ' + e.getMessage());
} 
    return JSON.serialize(lstwrap);
 }


  //Subclass : Wrapper Class 
public class Activitywrap {
    //Static Variables 
    public Date ActivityDate;
    public Date ActivityDay;
    public Decimal DailyHoursSpent;
    public String Status;

    //Wrapper  Class Controller
    Activitywrap () {
        Status ='Approved';
    }

}

}

BhatApp.Js

'use strict';

var bhatModule = angular.module('bhat', ['bhat.controllers',

                                                         'bhat.directives',

                                                         'bhat.filters',

                                                         'bhat.services']);

// Declare app level module which depends on filters, and services

/*

bhatModule.

config(['$routeProvider', function ($routeProvider) {

  $routeProvider

      .when('/', { templateUrl: sitePrefix + '/angular_vfremote_home', controller: 'MyCtrl1' })

      .when('/view1', {

          templateUrl: sitePrefix + '/angular_vfremote_partial1',

          controller: 'MyCtrl1'

      })

      .when('/view2', {

          templateUrl: sitePrefix + '/angular_vfremote_partial2',

          controller: 'MyCtrl2'

      })

      .otherwise({ redirectTo: '/' });

}]);

*/

// Declare app level module which depends on filters, and services

bhatModule.

config(['$routeProvider', function($routeProvider) {

$routeProvider.

    //when('/', { controller: HomeCtrl, templateUrl: sitePrefix + '/BhatActivitySummary.html' }).

    when('/', { controller: "ctrlActivitySummary", templateUrl: sitePrefix + '/BhatActivitySummary' }).

    //when('/login', { controller: LoginCtrl, templateUrl: sitePrefix + '/BhatLogin' }).

    when('/activitysummary', { controller: "ctrlActivitySummary", templateUrl: sitePrefix + '/BhatActivitySummary' }).

    when('/activitylist', { controller: "ctrlActivitySummary", templateUrl: sitePrefix + '/BhatActivityList' }).

    when('/activitydaily', { controller: "ActivitydailyCtrl", templateUrl: sitePrefix + '/BhatActivityDaily' }).

    when('/approverlist', { controller: "ctrlRead", templateUrl: sitePrefix + '/BhatApproverList' }).

    when('/approverweekly', { controller: "ctrlRead", templateUrl: sitePrefix + '/BhatApproverWeekly' }).

    when('/approversingle', { controller: "ActivitydailyCtrl", templateUrl: sitePrefix + '/BhatApproverSingle' }).

    when('/new', { controller: "ContactDetailCtrl", templateUrl: sitePrefix + '/BhatActivitySingle' }).

    when('/activitysingle', { controller: "ContactDetailCtrl", templateUrl: sitePrefix + '/BhatActivitySingle' }).

    when('/activitysingle', { controller: "ContactDetailCtrl", templateUrl: sitePrefix + '/BhatActivitySingle' }).

    otherwise({ redirectTo: '/activitysummary' });

}]);

Angular JS Controller: function being called on 'ctrlActivitySummary' controller.

'use strict';

/* Controllers */

var bhatModule = angular.module('bhat.controllers', []);

bhatModule.controller('ctrlActivitySummary', ['$scope', '$filter', '$location', '$http', '$log', 'doubleMe', 'getActivityList',

function ($scope, $filter, $location, $http, $log, doubleMe, getActivityList) {

    // init

    $scope.sortingOrder = sortingOrder;

    $scope.reverse = false;

    $scope.filteredItems = [];

    $scope.groupedItems = [];

    $scope.itemsPerPage = 7;

    $scope.pagedItems = [];

    $scope.currentPage = 0;





        getActivityList('test').then(function(result) {$scope.activityList = result;})

}])

Remoting Js:

// Create angular factory that defines service to call apex.

bhatModule.

factory('doubleMe', ['$q', '$rootScope', function ($q, $rootScope) {



    return function (inputString) {

        var deferred = $q.defer();



        Visualforce.remoting.Manager.invokeAction(

            '{!$RemoteAction.bhatindexcontroller.valueDoubler}',

            inputString,

            function (result, event) {

                $rootScope.$apply(function () {

                    if (event.status) {

                        deferred.resolve(result);

                    } else {

                        deferred.reject(event);

                    }

                })

            },

            { buffer: true, escape: true, timeout: 30000 }

        );



        return deferred.promise;

    }



}]);

// Module to get Activity List for the day.

bhatModule.

factory('getActivityList', ['$q', '$rootScope', function ($q, $rootScope) {



    return function (inputString) {



       var deferred = $q.defer();



        Visualforce.remoting.Manager.invokeAction(

            '{!$RemoteAction.bhatindexcontroller.getActivityList}',

            inputString,

            function (result, event) {

                $rootScope.$apply(function () {

                    if (event.status) {

                        deferred.resolve(result);

                    } else {

                        deferred.reject(event);

                    }

                })

            },

            { buffer: true, escape: true, timeout: 30000 }

        );



        return deferred.promise;

    }



}]);

Bryce Batson

unread,
Oct 31, 2013, 3:27:52 PM10/31/13
to ang...@googlegroups.com
I may be wrong, but I don't believe that you can use Visualforce tags {!} within a static resource file. Therefore, the invokeAction method is interpreting {!$RemoteAction.bhatindexcontroller.valueDoubler} as an undefined Javascript object. When calling Remote actions from a static resource, I generally use the other notation which is:
 
controllerName.methodName( [params,] function(result, event){
   //Processing here..
});

You could also try to copy and paste your Javascript into the page itself to see if it runs as written, which I believe it should as long as you don't include it in a static resource.
Reply all
Reply to author
Forward
0 new messages