1

I'm trying to get some information from a server in an html page of an AngularJS app. The method itself is working fine, however, when I call the function in my html file with $scope. I get a $rootScope:infidg Error.

Method in controller:

    $scope.getTranslation = function(){
        $http.get('https://producthero.com/index.php?option=com_hero&task=language.translate&s=SEARCH')
            .then(
                function (response) {
                    return response.data.translation;
                }
            );
    };

Call in html file with ng-app and ng-controller:

<div ng-controller="Product">
    <span>{{getTranslation()}}</span>
</div>

I'm using this way of translating because the initial backend of the site is running in Joomla, I know i18n, but we can't use it here.

The error is:

http://errors.angularjs.org/1.6.4/$rootScope/infdig?p0=10&p1=%5B%5D

angular.min.js:123 Error: [$rootScope:infdig] <http://errors.angularjs.org/1.6.4/$rootScope/infdig?p0=10&p1=%5B%5D>
    at angular.min.js:6
    at m.$digest (angular.min.js:147)
    at m.$apply (angular.min.js:149)
    at angular.min.js:21
    at Object.invoke (angular.min.js:44)
    at c (angular.min.js:21)
    at Sc (angular.min.js:22)
    at ue (angular.min.js:20)
    at HTMLDocument.<anonymous> (angular.min.js:331)
    at i (jquery.min.js:2)

I hope this is just me being stupid and that I'm missing something to make this kind of direct calls with http possible!

EDIT:

My solution on my translation problem is the following (thanks to @Aleksey Solovey for the answer):

Controller method

$scope.translations = {};

$scope.getTranslation = function(string){
    $http.get('https://producthero.com/index.php?option=com_hero&task=language.translate&s=' + string)
        .then(
            function (response) {
                $scope.translations[string] = response.data.translation;
            });
    };

View call

<div ng-app="products">

        <div ng-controller="Product">
            <span ng-init="getTranslation('SEARCH')">{{translations.SEARCH}}</span>
    </div>
</div>
1
  • The ng-init directive can be abused to add unnecessary amounts of logic into your templates. There are only a few appropriate uses of ngInit. See AngularJS ng-init API Reference. Commented Jul 12, 2018 at 10:53

2 Answers 2

1

$http request would return a Promise, not some value. So you need to populate a scoped variable first and then use it (asynchronously). Here is what it should look like:

var app = angular.module('myApp', []);
app.controller('Product', function($scope, $http) {
  $scope.getTranslation = function() {
    $http.get('https://producthero.com/index.php?option=com_hero&task=language.translate&s=SEARCH').
    then(function(response) {
      $scope.translation = response.data.translation;
    });
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>

<div ng-app="myApp">
  <div ng-controller="Product">
    <span ng-init="getTranslation()">{{translation}}</span>
  </div>
</div>

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

4 Comments

Ah, sounds logic. Thank you, this is working perfectly!
The ng-init directive can be abused to add unnecessary amounts of logic into your templates. There are only a few appropriate uses of ngInit. See AngularJS ng-init API Reference.
Could you give a different answer providing an example without using ng-init? If there is a more clean less intensive solution I would be glad to hear that from you @georgeawg
@DavidKooijman 'init' is for initialisation, simply initialise it manually in the controller with $scope.getTranslation()
0

Could you give a different answer providing an example without using ng-init?

Simply initialise it manually in the controller:

app.controller('Product', function($scope, $http) {
  $scope.getTranslation = function() {
    $http.get('https://producthero.com/index.php?option=com_hero&task=language.translate&s=SEARCH').
    then(function(response) {
      $scope.translation = response.data.translation;
    });
  };
  //INSTEAD OF ng-init
  $scope.getTranslation();
});
<div ng-app="myApp">
  <div ng-controller="Product">
    ̶<̶s̶p̶a̶n̶ ̶n̶g̶-̶i̶n̶i̶t̶=̶"̶g̶e̶t̶T̶r̶a̶n̶s̶l̶a̶t̶i̶o̶n̶(̶)̶"̶>̶{̶{̶t̶r̶a̶n̶s̶l̶a̶t̶i̶o̶n̶}̶}̶<̶/̶s̶p̶a̶n̶>̶
    <span>{{translation}}</span>
  </div>
</div>

The ng-init directive can be abused to add unnecessary amounts of logic into your templates. There are only a few appropriate uses of ngInit. See AngularJS ng-init API Reference.


Use of functions in HTML interpolation bindings with {{ }} should be avoided for performance reasons. Those functions are called one or more times per digest cycle.

Erroneous

<div ng-controller="Product">
    <span>{{getTranslation()}}</span>
</div>

Asynchronous functions that return promises will cause infinite digest errors.

For more information, see

3 Comments

Ah, I get what you mean! But I have a lot of translations that I need to do on the fly with ng-repeat on a product list etc. That's why i want it to be generated in the view although it seems to be not the best solution! Thanks for you answer though
There are ways to avoid ng-init in ng-repeat. It is involves chaining promises and using $q.all. It avoids tangling Model and View. The result is code that is easier to understand, debug, test, and maintain.
I'll have a look into that as well. Thanks for all the info!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.