简体   繁体   English

从 Aurelia 视图模型中的 canActivate 导航

[英]Navigating from canActivate in Aurelia view-model

In my Aurelia view-model, I am trying to check some precondition, in canActivate() , and based on that it is decided whether navigate to a different view or not.在我的 Aurelia 视图模型中,我试图在canActivate()检查一些先决条件,并基于此决定是否导航到不同的视图。

export class ThisView{

    canActivate() {        
        const self = this;
        const promise = self.services.get(url)
            .then((items: any) => {
                if (items) {
                    self.items= items;
                    if (self.items.length === 1) {
                        this.router.navigate("some/other/view");
                        //return false; 
                    }
                    //return true;
                } else {
                    self.logger.error("No item found");
                    //return false;
                }                
            });
        return promise;
    }
}

Now even though I am navigating to some/other/view if there is only one item found, view of ThisView still gets activated (ie can be seen in browser).现在,即使我导航到some/other/view如果只找到一个项目, ThisView视图仍然被激活(即可以在浏览器中看到)。

Is there a way, to avoid that?有没有办法避免这种情况? There couple of things I tried for this.我为此尝试了几件事。

  1. Return true , or false from promise to accept, or reject activation of this view.promise返回truefalse以接受或拒绝此视图的激活。 But as this view is kind of landing page of my application, if rejected (returned false) it tries to restore the previous location, which is not available, and throws an error.但是由于这个视图是我的应用程序的一种登陆页面,如果被拒绝(返回 false),它会尝试恢复先前不可用的位置,并引发错误。 And restoring a previous location is also not desired by the application for this specific case.对于这种特定情况,应用程序也不希望恢复先前的位置。
  2. Another idea was to do something like a pipeline step where we can do something like next.cancel(new Redirect("some/other/view")) , where we can instruct to cancel the current navigation instruction with a new one.另一个想法是做一些类似于管道步骤的事情,我们可以在其中执行类似next.cancel(new Redirect("some/other/view")) ,我们可以在其中指示使用新的导航指令取消当前导航指令。 But I am not sure how to do the same from a view-model.但我不确定如何从视图模型中做同样的事情。

Please suggest.请建议。

Workaround: I have finally used a simple trick of using if.bind on view of ThisView .解决方法:我终于使用了一个简单的技巧, if.bindif.bind视图上使用ThisView However, it could have been more interesting, if we can somehow cancel the current instruction (from page lifecycle) with a new one.然而,如果我们能以某种方式用新指令取消当前指令(来自页面生命周期),它可能会更有趣。

instead of this.router.navigate("some/other/view) can you not import redirect and add the redirect in there, ie而不是 this.router.navigate("some/other/view) 你不能导入重定向并在那里添加重定向,即

import {Redirect} from 'aurelia-router';

export class ThisView{

canActivate() {        
    const self = this;
    var items = self.services.get(url);
    if(items){
        self.items= items;
        if (self.items.length === 1) {
           return new Redirect("some/other/view");
        }
        return true;
    } 
    else {
        self.logger.error("No item found");
        return new Redirect("not-found-view");
    }                
}

} }

I've made a basic GistRun showing how this works - I haven't used a promise, but I believe the concept is the same.我已经做了一个基本的 GistRun 来展示它是如何工作的——我没有使用承诺,但我相信这个概念是一样的。

https://gist.run/?id=52301f1b2898691ff4d54f320f61f6c6 https://gist.run/?id=52301f1b2898691ff4d54f320f61f6c6

You can use activate() event to process router navigation.您可以使用activate()事件来处理路由器导航。 Throw error to stop navigation or goto/redirect to another location.抛出错误以停止导航或转到/重定向到另一个位置。 Example:示例:

import {Router} from 'aurelia-router';

export class SampleModel {
  static inject() { return [Router] };

  constructor(router) {
    this.router = router;
  }

  activate(){
    if(this.somedata === null){
      // stop navigation or goto start location
      if(this.router.history.previousLocation){
        // stop from navigation
        throw new Error('Wrong data');
      }else{
        // return to start page
        this.router.navigate('start');
      }
    }
  }
}

You could also inject some middleware in the router pipeline the same way authorization steps are done.您还可以以与完成授权步骤相同的方式在路由器管道中注入一些中间件。

You would then call your service in a particular step and route to a different view depending on the result.然后,您将在特定步骤中调用您的服务,并根据结果路由到不同的视图。

Some code snippets on how steps are added to the router pipeline can be found here: Aurelia: During a Router's Pipeline Step, how do I bind a variable to that router?可以在此处找到有关如何将步骤添加到路由器管道的一些代码片段: Aurelia:在路由器的管道步骤期间,如何将变量绑定到该路由器?

I figured out another way to handle navigation in canActive()我想出了另一种在 canActive() 中处理导航的方法

   canActivate(params, routeConfig, navigationInstruction) {

        return new Promise((resolve, reject) => {

            this.api.request(params.id).then(result => {

                if (result) {
                    resolve(true);
                } else {
                    toastr.error('Invalid URL');
                    reject(navigationInstruction.router.navigate('/xxx'));
                }
            }).catch(error => {
                toastr.error('Request error');
                resolve(false);
            });
        });
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM