Angularjs $rootScope:infdig Ошибка при вызове http в методе просмотра

Я пытаюсь получить некоторую информацию с сервера на html-странице приложения AngularJS. Однако сам метод работает нормально, когда я вызываю функцию в своем html-файле с помощью $scope. Я получаю ошибку $rootScope:infidg.

Метод в контроллере:

    $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;
                }
            );
    };

Вызовите html-файл с помощью ng-app и ng-controller:

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

Я использую этот способ перевода, потому что начальный бэкенд сайта работает на Joomla, я знаю i18n, но мы не можем использовать его здесь.

Ошибка:

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)

Я надеюсь, что это просто я глуп и что мне чего-то не хватает, чтобы сделать возможными такие прямые звонки с http!

РЕДАКТИРОВАТЬ:

Мое решение моей проблемы с переводом следующее (спасибо @Aleksey Solovey за ответ):

Метод контроллера

$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;
            });
    };

Просмотр звонка

<div ng-app="products">

        <div ng-controller="Product">
            <span ng-init="getTranslation('SEARCH')">{{translations.SEARCH}}</span>
    </div>
</div>

person David Kooijman    schedule 12.07.2018    source источник
comment
Директивой ng-init можно злоупотреблять, добавляя ненужное количество логики в ваши шаблоны. Есть только несколько подходящих вариантов использования ngInit. См. Справочник по API AngularJS ng-init.   -  person georgeawg    schedule 12.07.2018


Ответы (2)


$http запрос вернет обещание, а не какое-то значение. Поэтому вам нужно сначала заполнить переменную области действия, а затем использовать ее (асинхронно). Вот как это должно выглядеть:

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>

person Aleksey Solovey    schedule 12.07.2018
comment
А, звучит логично. Спасибо, это работает отлично! - person David Kooijman; 12.07.2018
comment
Директивой ng-init можно злоупотреблять, добавляя ненужное количество логики в ваши шаблоны. Есть только несколько подходящих вариантов использования ngInit. См. Справочник по API AngularJS ng-init. - person georgeawg; 12.07.2018
comment
Не могли бы вы дать другой ответ, приведя пример без использования ng-init? Если есть более чистое, менее интенсивное решение, я был бы рад услышать это от вас @georgeawg - person David Kooijman; 12.07.2018
comment
@DavidKooijman 'init' предназначен для инициализации, просто инициализируйте его вручную в контроллере с помощью $scope.getTranslation() - person Aleksey Solovey; 12.07.2018

Не могли бы вы дать другой ответ, приведя пример без использования ng-init?

Просто инициализируйте его вручную в контроллере:

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>

Директивой ng-init можно злоупотреблять, добавляя ненужное количество логики в ваши шаблоны. Есть только несколько подходящих вариантов использования ngInit. См. Справочник по API AngularJS ng-init.


Использование функций в привязках интерполяции HTML с {{ }} следует избегать по соображениям производительности. Эти функции вызываются один или несколько раз за цикл дайджеста.

ошибочный

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

Асинхронные функции, возвращающие промисы, вызовут бесконечные ошибки дайджеста.

Для получения дополнительной информации см.

person georgeawg    schedule 12.07.2018
comment
Ах, я понимаю, что вы имеете в виду! Но у меня есть много переводов, которые мне нужно сделать на лету с помощью ng-repeat в списке продуктов и т. Д. Вот почему я хочу, чтобы он генерировался в представлении, хотя это кажется не лучшим решением! Спасибо за ответ, хотя - person David Kooijman; 12.07.2018
comment
Есть способы избежать ng-init в ng-repeat. Это включает в себя цепочку промисов и использование $q.all. Это позволяет избежать путаницы Model и View. В результате получается код, который легче понимать, отлаживать, тестировать и поддерживать. - person georgeawg; 12.07.2018
comment
Я тоже посмотрю на это. Спасибо за всю информацию! - person David Kooijman; 12.07.2018