在运行时更改元素类型

时间:2017-03-02 13:45:31

标签: aurelia aurelia-templating

是否可以在运行时动态定义自定义组件模板中元素的类型?

我想避免在以下示例中重复buttona元素的内部内容:

<template>
    <button if.bind="!isLinkBtn">
        <span class="btn-icon">${icon}</span>
        <span class="btn-text">${contentText}</span>
    </button>

    <a if.bind="isLinkBtn">
        <!--
        The content is a 1:1 duplicate of the button above which should be prevented
        somehow in order to keep the view DRY
        -->
        <span class="btn-icon">${icon}</span>
        <span class="btn-text">${contentText}</span>
    </a>
</template>

是否可以写下这样的内容:

<template>
    <!--
    The type of element should be defined at runtime and can be a standard HTML "button"
    or an anchor "a"
    -->
    <element type.bind="${isLinkBtn ? 'a' : 'button'}">
        <span class="btn-icon">${icon}</span>
        <span class="btn-text">${contentText}</span>
    </element>
</template>

我知道<compose view="${widget.type}-view.html"></compose>的动态构图,但据我所知,这不允许我创建默认的HTML元素,只允许自定义组件,对吗?

我在Aurelia Gitter上问过这个问题,Erik Lieben建议使用@processContent(function)装饰器,替换给定function内的内容并返回true让Aurelia处理它

不幸的是,我不知道如何实际应用这些说明,我希望在这里有一些替代方法或者有关如何实现这一目标的一些细节。

修改

我已经创建了相应的feature request。即使已经提供了可能的解决方案,我也希望看到一些更简单的解决方法;)

2 个答案:

答案 0 :(得分:3)

如果要重复使用HTML代码段,请使用撰写。这样做创建新的自定义元素。它只是在每个撰写元素的位置包含HTML。因此,包含HTML的视图模型与组成它的元素相同。

看看这个GistRun:https://gist.run/?id=36cf2435d39910ff709de05e5e1bedaf

自定义-link.html

<template>
    <button if.bind="!isLinkBtn">
      <compose view="./custom-link-icon-and-text.html"></compose>
    </button>

    <a if.bind="isLinkBtn" href="#">
      <compose view="./custom-link-icon-and-text.html"></compose>
    </a>
</template>

自定义-link.js

import {bindable} from 'aurelia-framework';

export class CustomLink {
    @bindable() contentText;
    @bindable() icon;
    @bindable() isLinkBtn;
}

自定义链路图标和 - text.html

<template>
    <span class="btn-icon">${icon}</span>
    <span class="btn-text">${contentText}</span>
</template>

<强> consumer.html

<template>
  <require from="./custom-link"></require>
  <custom-link content-text="Here is a button"></custom-link>
  <custom-link is-link-btn.bind="true" content-text="Here is a link"></custom-link>
</template>

您可能希望将这些元素拆分为单独的元素,例如<custom-button><custom-link>,而不是使用is-link-btn属性控制其演示。您可以使用相同的技术重复使用常见的HTML部件和装饰器来重用公共代码。

请参阅此GistRun:https://gist.run/?id=e9572ad27cb61f16c529fb9425107a10

回应你的&#34;更少详细&#34;评论

您可以将其归结为一个文件,并使用上述GistRuncompose装饰器中的技术避免inlineView

请参阅此GistRun:https://gist.run/?id=4e325771c63d752ef1712c6d949313ce

您只需要这个文件:

自定义-links.js

import {bindable, inlineView} from 'aurelia-framework';

function customLinkElement() {
    return function(target) {
        bindable('contentText')(target);
        bindable('icon')(target);
  }
}


const tagTypes = {button: 'button', link: 'a'};


@inlineView(viewHtml(tagTypes.button))
@customLinkElement()
export class CustomButton {

}


@inlineView(viewHtml(tagTypes.link))
@customLinkElement()
export class CustomLink {

}


function viewHtml(tagType) {
  let result = `
    <template>
        <${tagType}${tagType === tagTypes.link ? ' href="#"' : ''}>
            <span class="btn-icon">\${icon}</span>
            <span class="btn-text">\${contentText}</span>
        </${tagType}>
    </template>
    `;

  return result;
}

答案 1 :(得分:1)

对不起,我一边做两件事,一边看着gitter,我显然不擅长: - )

对于你最终要完成的事情,这也可以吗?

我不是一个专家或者在这方面有很多知识,但据我所知,这将实现你想要的。浏览器将查看角色属性并将其作为链接或按钮处理,并忽略实际的元素类型本身/不管它是按钮还是锚点,它将表现为它是角色中定义的类型。

然后,您可以使用css将其设置为按钮或链接标记。

<a role.bind="type"><span>x</span><span>y</span></a>

其中type是链接或按钮,请参阅:https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_link_role