英文:
Making a custom angular component from another library clickable with "enter" key
问题
问题
tl;dr: 我正在创建的一个角度组件无法通过回车键点击。
我有一个使用stencil构建的库,它定义并创建了一堆要在一组应用程序中使用的角度组件。
我试图创建一个导航链接,以从该库中使用:
@Component({
  tag: "test-nav-link",
  styleUrl: "test-nav-link.css",
  shadow: true,
})
export class TestNavLink {
  @Prop() href?: string;
  @Prop() label?: string;
  @Prop() target?: string;
  @Prop() rel?: string;
  @Prop() active = false;
  @Prop() icon?: IconList;
  @Prop() iconsize = IconSizeList.md;
  render() {
    return (
      <a
        data-active={this.active}
        href={this.href}
        target={this.target}
        rel={this.rel}
      >
        {this.icon && (
          <icon
            icon={this.icon}
            iconsize={this.iconsize}
            icontype={IconTypeList.text}
          />
        )}
        {this.label}
      </a>
    );
  }
}
然后,我可以在我的一个应用程序的导航栏中使用它,如下所示:
<test-layout-nav>
  <test-nav-link routerLink="site"
                 routerLinkActive="{{ activeClass }}"
                 label="Site">
  </test-nav-link>
  <test-nav-link routerLink="page"
                 routerLinkActive="{{ activeClass }}"
                 label="Page">
  </test-nav-link>
  <div class="nav-actions" slot="actions">
    <app-search></app-search>
    <settings></settings>
  </div>
</test-layout-nav>
如果使用href(即在我们没有访问权限的某些空间之一),则此方法有效。
当使用角度的routerLink时,不起作用 - 它可以正确呈现,我可以按按钮,甚至可以通过Tab键导航到它,但当我按Enter键时,它不起作用。
我尝试过的事情
将routerLink添加到组件
我尝试将routerLink添加为组件上的附加@Prop,然后更改href为:
href={this.href ? this.href | this.routerLink}
这使其可以点击,但然后页面会加载两次;一次通过routerLink,一次通过href。
在使用code的地方添加keydown.enter
我可以更改导航使用如下:
<test-nav-link routerLink="site"
               routerLinkActive="{{ activeClass }}"
               (keydown.enter)="onEnter('site')"
               label="Site">
</test-nav-link>
这可以工作,但感觉它添加了大量样板代码;拥有单独的组件库的目的是您只需编写这些内容一次,然后可以在任何地方使用组件。
其他
我尝试了一些与tabindex=-1有关的奇怪操作,以查看是否可以强制锚元素可点击,但是,没有成功。
有什么建议吗?我唯一剩下的想法是放弃这个组件的想法,回到只使用<a>。
英文:
The problem
tl;dr: An angular component I'm creating isn't clickable via enter.
I have a library built with stencil that defines & creates a bunch of angular components to use across a set of apps.
I'm trying to create a navigation link to use from that library:
@Component({
  tag: "test-nav-link",
  styleUrl: "test-nav-link.css",
  shadow: true,
})
export class TestNavLink {
  @Prop() href?: string;
  @Prop() label?: string;
  @Prop() target?: string;
  @Prop() rel?: string;
  @Prop() active = false;
  @Prop() icon?: IconList;
  @Prop() iconsize = IconSizeList.md;
  render() {
    return (
      <a
        data-active={this.active}
        href={this.href}
        target={this.target}
        rel={this.rel}
      >
        {this.icon && (
          <icon
            icon={this.icon}
            iconsize={this.iconsize}
            icontype={IconTypeList.text}
          />
        )}
        {this.label}
      </a>
    );
  }
}
And then I can use this in the navbar for one of my apps as so:
<test-layout-nav>
  <test-nav-link routerLink="site"
                 routerLinkActive="{{ activeClass }}"
                 label="Site">
  </test-nav-link>
  <test-nav-link routerLink="page"
                 routerLinkActive="{{ activeClass }}"
                 label="Page">
  </test-nav-link>
  <div class="nav-actions" slot="actions">
    <app-search></app-search>
    <settings></settings>
  </div>
</test-layout-nav>
This works if you use href (i.e. in one of the spaces where we don't have access to angular).
This does not work when using angular's routerLink - it renders fine, I can press the button, I can even tab to it, but when I press enter, it doesn't act as a link.
What I've tried
Adding routerLink to the component
I've tried adding routerLink as an additional @Prop on the component, and then changing the href to:
href={this.href ? this.href | this.routerLink}
This makes it clickable, but then the page loads twice; once via routerLink, once via href.
Adding keydown.enter where code is used
I can change the nav usage to look as follows:
  <test-nav-link routerLink="site"
                 routerLinkActive="{{ activeClass }}"
                 (keydown.enter)="onEnter('site')"
                 label="Site">
  </test-nav-link>
This works, but it feels like it adds a lot of boilerplate; the point of having a separate library of components is that you need to write stuff like this once, and then can use the components everywhere.
Other
I tried some weird stuff with tabindex=-1 to see if I could force the anchor element to be clickable, but yeah, no dice.
Any advice? The only thing I can think of left is scrap this component as an idea and go back to using <a> on its own.
答案1
得分: 1
If you look at the documentation, you will see that the routerLink is actually a directive that manages the clicks for you (line 267~ish)
So, given that, you can probably try to trigger a click when you press enter:
<test-nav-link #link routerLink="site"
                 routerLinkActive="{{ activeClass }}"
                 (keydown.enter)="link.click()"
                 label="Site">
  </test-nav-link>
Or this one, maybe:
<test-nav-link routerLink="site"
                 routerLinkActive="{{ activeClass }}"
                 (keydown.enter)="$any($event.target).click()"
                 label="Site">
  </test-nav-link>
英文:
If you look at the documentation, you will see that the routerLink is actually a directive that manages the clicks for you (line 267~ish)
So, given that, you can probably try to trigger a click when you press enter :
<test-nav-link #link routerLink="site"
                 routerLinkActive="{{ activeClass }}"
                 (keydown.enter)="link.click()"
                 label="Site">
  </test-nav-link>
Or this one, maybe :
<test-nav-link routerLink="site"
                 routerLinkActive="{{ activeClass }}"
                 (keydown.enter)="$any($event.target).click()"
                 label="Site">
  </test-nav-link>
答案2
得分: 1
要添加到MGX上面的帖子中,这很容易映射到模板库中:
  @Listen('keydown')
  handleKeyDown(ev: KeyboardEvent) {
    if (ev.key === 'Enter') {
      if (this.routerLink !== undefined) {
        this.hostElement.click();
      }
    }
  }
谢谢MGX!
英文:
To add to MGX's post above, this is pretty easy to map to the stencil library:
  @Listen('keydown')
  handleKeyDown(ev: KeyboardEvent) {
    if (ev.key === 'Enter') {
      if (this.routerLink !== undefined) {
        this.hostElement.click();
      }
    }
  }
Thanks MGX!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论