如何在导航栏中绑定App方法

Aurelia: How to bind App method in Navbar?

本文关键字:绑定 App 方法 导航      更新时间:2023-09-26

我花了一些时间试图得到这个工作正常的布线,不能。我不知道我做错了什么。到目前为止,我找到的关于这个问题的最佳参考是导航栏中的Aurelia Binding Click Trigger。我尝试了这种方法,但仍然得到相同的错误:

Uncaught Error: authenticate is not a function(…)in aurelia-binding.js:1965 (getFunction)

我的设置如下:

nav-bar.html

<template bindable="router, authenticate">
    <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse-main">
                <span class="sr-only">Toggle Navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">
                <i class="fa fa-home"></i>
                <span>${router.title}</span>
            </a>
        </div>
        <div class="collapse navbar-collapse" id="navbar-collapse-main">
            <ul class="nav navbar-nav">
                <li repeat.for="row of router.navigation | authFilter: authenticated" class="${row.isActive ? 'active' : ''}">
                    <a data-toggle="collapse" data-target="#navbar-collapse-main.in" href.bind="row.href">${row.title}</a>
                </li>
            </ul>
            <ul if.bind="authenticated" class="nav navbar-nav navbar-right">
                <li>${userName}</li>
                <li><a href="/#/logout">Logout</a></li>
            </ul>
            <ul if.bind="!authenticated" class="nav navbar-nav navbar-right">
                <li><a id="loginLink" click.trigger="authenticate()">Login</a></li>
                <li>&nbsp;&nbsp;</li>
            </ul>
            <ul class="nav navbar-nav navbar-right">
                <li class="loader" if.bind="router.isNavigating">
                    <i class="fa fa-spinner fa-spin fa-2x"></i>
                </li>
            </ul>
        </div>
    </nav>
</template>

app.html

<template>
    <require from="./views/shared/nav-bar.html"></require>
    <require from="bootstrap/css/bootstrap.css"></require>
    <nav-bar router.bind="router" authenticate.call="authenticate()"></nav-bar>
    <div class="page-host">
        <div class="container-fluid">
            <router-view></router-view>
        </div>
    </div>
</template>

app.ts

import {inject, computedFrom} from "aurelia-framework";
import {Router, RouterConfiguration} from 'aurelia-router'
import {AuthService, AuthenticateStep} from 'aurelia-authentication';
import {log} from "./services/log";
@inject(AuthService)
export class App {
   authService: AuthService;
   router: Router;
   userName: string;
   constructor(auth) {
      this.authService = auth;
   }
  configureRouter(config: RouterConfiguration, router: Router) {
  config.title = 'AppName';
  config.addPipelineStep('authorize', AuthenticateStep);
  config.map([
     { route: ['', 'welcome'], name: 'welcome', moduleId: 'views/welcome', nav: true, title: 'Welcome' },
     { route: "orgTypes", name: "orgTypes", moduleId: "views/orgTypes", nav: true, auth: true, title: "Organization Types" },
     { route: "credits", name: "credits", moduleId: "views/credits", nav: true, auth: true, title: "Application Credits" }
  ]);
  this.router = router;
   }
   authenticate() {
   return this.authService.authenticate('identityServer')
     .then((response) => {
        log.info("login successful");
     });
   };

   @computedFrom('authService.authenticated')
   get authenticated() {
      return this.authService.authenticated;
   }
}

在App VM中绑定子视图的方法是什么?

编辑1:在FabioLuz的第二条评论之后

Fabio的建议是有效的,应该是有效的。你可能有其他问题阻止它工作。

你能像这样简化App.authenticate()来检查它吗?只是为了排除底层可能出现的错误。

authenticate() {
  log.info("login successful");
}

另一个猜想:

./services/log是静态对象吗?如果不是,则可能缺少注入。

既然你使用的是TypeScript, autoinject可能会帮助你避免类似的陷阱。

import {autoinject, computedFrom} from "aurelia-framework";
import {AuthService, AuthenticateStep} from 'aurelia-authentication';
import {log} from "./services/log";
@autoinject()
export class App {
  authService: AuthService;
  logger: log;
  constructor(auth: AuthService, logger: log) {
    this.authService = auth;
    this.logger = logger;
  }
}

在App VM中绑定子视图的方法是什么?

我知道3种可能的解决方案来实现这一目标(可能还有更多)。我已经创建了一个要点来展示这些操作。

https://gist.run/?id=b9e8fee11e338e08bc5da7d4df68e2db

使用下拉菜单在导航条实现之间切换。:)

1。HTML元素+ bindables

这是你当前的场景。参见示例中的nav-bar-function.html

2。<compose> + inheritance

组合在一些动态场景中很有用,但尽量不要过度使用。(博客)

当没有提供模型时,组合元素继承父元素的视图模型上下文。

通常我不建议在你的情况下使用它。但是,考虑到解决方案1的问题。,您可以将此选项用于调试目的。如果您在<compose>中也得到相同的错误,则可能是App.authenticate()函数本身有问题。

通过替换

在您的解决方案中尝试一下

<nav-bar router.bind="router" authenticate.call="authenticate()"></nav-bar>

<compose view="./nav-bar.html"></compose>

这样,nav-bar.html作为App组件的一部分。参见示例中的nav-bar-compose.html

3。自定义元素+ EventAggregator

你可以在组件之间使用pub/sub通信*来避免紧耦合。相关SO答案:[访问自定义组件数据/方法]和[文档]

*components:使用视图模型类自定义元素


我希望它会有帮助!:)