как поймать угловую ошибку ng-include

Когда я использую ng-include в качестве заголовка, как мне поймать ошибку, когда адрес (путь к файлу) не существует?

Я закончил ng-include router внутри ng-view(with ng-route), это примерно так:

КонтентCtrl:

var content = $route.current.params.content,
    tmplArr = content.split("_"),
    tmpl = {},
    personId=$route.current.params.personId||$scope.persons[0].id;
$scope.personId=personId;
tmpl.url = "content/";
for (var i = 0, len = tmplArr.length; i < len; i++) {
    tmpl.url += tmplArr[i] + "/";
}
tmpl.url = tmpl.url.substring(0, tmpl.url.length - 1) + ".html";
$scope.template = tmpl;

Просмотр содержания:

<div ng-include="template.url" class="ng-animate"></div>

когда я использую адрес, который не существует, например:/home/#/content/profile_asdfa, angular просто извлекает ресурс в цикле. Поэтому мне нужно поймать ошибку ng-include, когда в хеше нет файла шаблона. Кто-нибудь может мне помочь ? Спасибо!


person Tyler.z.yang    schedule 30.12.2013    source источник
comment
Не имеет отношения к вашему вопросу, но может быть лучше не включать класс ng-animate в элемент. Это добавляется (+ удаляется) автоматически, когда Angular выполняет анимацию входа/выхода, поэтому это может привести к немного непредсказуемому поведению.   -  person Michal Charemza    schedule 30.12.2013


Ответы (1)


В источнике ngInclude есть похоже, нет ловушки или способа напрямую обнаружить ошибку 404 (или другую), когда шаблон не существует. Возможно, вы захотите рассмотреть запрос функции, чтобы добавить это, так как это звучит как полезная функция.

Однако прямо сейчас вы можете что-то сделать с перехватчиком ответа http. Если есть какой-то способ определить, относится ли http-запрос к шаблону, скажем, он находится в каталоге «content», вы можете перехватывать ошибки и что-то с ними делать. Например, вы можете заменить данные пользовательской директивой, которая затем генерирует событие, чтобы контроллеры могли реагировать на него.

Перехватчик может быть записан так:

app.config(function ($httpProvider) {
    $httpProvider.interceptors.push('templateInterceptor');
});

// register the interceptor as a service
app.factory('templateInterceptor', function($q) {
  return {
    'responseError': function(rejection) {
       var isTemplate = !!rejection.config.url.match(/^content/g);
       if (isTemplate) {
         rejection.data = '<div><template-error url="\''+ (rejection.config.url) + '\'"><strong>Error from interceptor.</strong></template-error></div>';
         return rejection;
       } else {
         return $q.reject(rejection);
       }
    }
  }
});

Поэтому, когда возникает ошибка после извлечения чего-либо из директивы «content», он добавляет элемент <template-error> вместо содержимого шаблона. Когда это скомпилировано, а затем связано, это $emit является пользовательским событием, templateError, на которое родительские контроллеры могут реагировать, $scope.$on. Таким образом, директива может быть закодирована следующим образом:

app.directive('templateError', function() {
  return {
    restrict: 'E',
    scope: {
      'url': '='
    },
    link: function(scope) {
      scope.$emit('templateError', {url:scope.url});
    }
  };
});

И тогда в родительском контроллере оригинального ngInclude можно отреагировать на это событие:

$scope.$on('templateError', function(e, data) {
  $scope.templateError = true;
  $scope.templateErrorUrl = data.url;
})

Вы можете увидеть полный рабочий код в этом плункере. Хотя я думаю, что это немного взломано, если команда Angular решит добавить событие $emited к коду ngInclude при ошибке, тогда будет легко просто удалить перехватчик/ваш пользовательский элемент.

person Michal Charemza    schedule 30.12.2013
comment
Кажется, ваша схема может решить мою проблему, я попробую позже. Большое спасибо : ) - person Tyler.z.yang; 31.12.2013
comment
Могу ли я предположить, что то же самое решение будет работать при загрузке шаблона ng-view? - person Ruben Decrop; 02.09.2014
comment
@ruben Я не понимаю, почему бы и нет ... Вы всегда можете попробовать и посмотреть :-) - person Michal Charemza; 04.09.2014