如何捕获角度ng-include错误

时间:2022-08-25 23:54:25

When I use ng-include as a title, how do I catch the error when the address (file path) does not exist?

当我使用ng-include作为标题时,如何在地址(文件路径)不存在时捕获错误?

I finished a ng-include router inside a ng-view(with ng-route), It's a little bit like this:

我在ng-view(使用ng-route)中完成了一个ng-include路由器,它有点像这样:

ContentCtrl:

ContentCtrl:

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;

ContentView:

内容查看:

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

when I use the addr is not exist like:/home/#/content/profile_asdfa, the angular just fetch the resource in a loop. So I need to catch the ng-include error,when there is no template file in the hash. Can anybody Help me ? Thx!

当我使用addr时不存在如:/ home /#/ content / profile_asdfa,angular只是在循环中获取资源。所以当哈希中没有模板文件时,我需要捕获ng-include错误。有谁能够帮助我 ?谢谢!

1 个解决方案

#1


13  

Looking in the source for ngInclude, there seems to be no hook or way to detect directly a 404 (or other) error when the template doesn't exist. You might want to consider a feature request to add this, as it sounds like a useful feature.

查看ngInclude的源代码,当模板不存在时,似乎没有挂钩或方法直接检测404(或其他)错误。您可能需要考虑添加此功能的功能请求,因为它听起来像一个有用的功能。

However, right now you could do something with a http response interceptor. If there is some way to tell if a http reguest is for a template, say it is in the 'content' directory, you can intercept errors, and do something with them. For example you could replace the data with a custom directive, that then emits an event so controller(s) could respond to it.

但是,现在你可以使用http响应拦截器做一些事情。如果有一种方法可以判断http reguest是否适用于模板,例如它位于“content”目录中,您可以拦截错误,并对它们执行某些操作。例如,您可以使用自定义指令替换数据,然后发出一个事件,以便控制器可以响应它。

The interceptor could be written like:

拦截器可以写成:

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

So when there is an error after fetching something from the 'content' directive, it adds an element <template-error> in place of the template content. When this is compiled and then linked, it $emits a custom event, templateError, which parent controllers can respond to, by $scope.$on. So the directive can be code up like:

因此,当从'content'指令中获取内容后出现错误时,它会添加一个元素 来代替模板内容。当编译然后链接它时,它会发出一个自定义事件templateError,父控制器可以通过$ scope。$ on响应。所以该指令可以编码如下:

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

And then in the parent controller of the original ngInclude, you can react to this event:

然后在原始ngInclude的父控制器中,您可以对此事件做出反应:

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

You can see the full working code in this Plunker. Although I think this is slightly hacky, if the Angular team decide to add an $emited event to the code of ngInclude on error, then it should be easy to just remove the interceptor / your custom element.

您可以在此Plunker中看到完整的工作代码。虽然我认为这有点hacky,但如果Angular团队决定在错误的ngInclude代码中添加一个$ emited事件,那么删除拦截器/你的自定义元素应该很容易。

#1


13  

Looking in the source for ngInclude, there seems to be no hook or way to detect directly a 404 (or other) error when the template doesn't exist. You might want to consider a feature request to add this, as it sounds like a useful feature.

查看ngInclude的源代码,当模板不存在时,似乎没有挂钩或方法直接检测404(或其他)错误。您可能需要考虑添加此功能的功能请求,因为它听起来像一个有用的功能。

However, right now you could do something with a http response interceptor. If there is some way to tell if a http reguest is for a template, say it is in the 'content' directory, you can intercept errors, and do something with them. For example you could replace the data with a custom directive, that then emits an event so controller(s) could respond to it.

但是,现在你可以使用http响应拦截器做一些事情。如果有一种方法可以判断http reguest是否适用于模板,例如它位于“content”目录中,您可以拦截错误,并对它们执行某些操作。例如,您可以使用自定义指令替换数据,然后发出一个事件,以便控制器可以响应它。

The interceptor could be written like:

拦截器可以写成:

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

So when there is an error after fetching something from the 'content' directive, it adds an element <template-error> in place of the template content. When this is compiled and then linked, it $emits a custom event, templateError, which parent controllers can respond to, by $scope.$on. So the directive can be code up like:

因此,当从'content'指令中获取内容后出现错误时,它会添加一个元素 来代替模板内容。当编译然后链接它时,它会发出一个自定义事件templateError,父控制器可以通过$ scope。$ on响应。所以该指令可以编码如下:

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

And then in the parent controller of the original ngInclude, you can react to this event:

然后在原始ngInclude的父控制器中,您可以对此事件做出反应:

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

You can see the full working code in this Plunker. Although I think this is slightly hacky, if the Angular team decide to add an $emited event to the code of ngInclude on error, then it should be easy to just remove the interceptor / your custom element.

您可以在此Plunker中看到完整的工作代码。虽然我认为这有点hacky,但如果Angular团队决定在错误的ngInclude代码中添加一个$ emited事件,那么删除拦截器/你的自定义元素应该很容易。