2017-03-02 17 views
3

実行時にカスタムコンポーネントテンプレート内のエレメントのタイプを動的に定義することは可能ですか?実行時にエレメントタイプを変更する

私は、次の例に buttona要素の内側の内容の重複を避けるしたいと思い

<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> 

I:このような何かを書くこと

<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> 

ことが可能です<compose view="${widget.type}-view.html"></compose>で動的な構成を認識していますが、私の知る限り、これはデフォルトのHTML要素を作成することはできませんが、カスタムコンポーネントのみを作成することはできません。

私はエリックリーベンは、@processContent(function)デコレータを使用して与えられたfunction内のコンテンツを交換し、オーレリアはそれを処理できるようにtrueを返すことが示唆アウレリアギッターにこの質問をしてきました。

残念ながら、実際にこれらの手順を実際に適用する方法はわかりませんし、ここでいくつかの代替アプローチや実際にこれを達成する方法の詳細を期待しています。


編集

私は、対応するfeature requestを作成しました。可能な解決法が提供されていても、私はこれを解決する簡単な方法を見たいと思っています;)

+0

' processContent'が、この場合に役立つことはありませんが。 –

答えて

3

HTMLスニペットを再利用するには、そうすると、ではなく、が新しいカスタム要素を作成します。これは、単に各compose要素の場所に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; 
} 

カスタムリンクアイコンを-and-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を参照してください:あなたは一つのファイルにそれを取得し、上記GistRunにおける技術とinlineViewデコレータを使用してcomposeを避けることができますあなたの「それほど冗長」のコメント

からhttps://gist.run/?id=e9572ad27cb61f16c529fb9425107a10

応答:すべてあなたが旧姓うhttps://gist.run/?id=4e325771c63d752ef1712c6d949313ce

このGistRunを参照してください。

カスタム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

覚えておくべきことは、 'compose'を使用してHTMLの小さな部分を取り込むことは、DRYやコードのインライン展開以外のパフォーマンスが大幅に低下することです。この質問の特定の例では、おそらく、 'compose'を使う代わりにHTMLを繰り返すことに頼るでしょう。 HTMLのより大きなブロックを組み立てれば、もっと理にかなっています。あなたが与えた答えは正しいです、ちょうど私が言及した注意書きで。 –

+1

合意されたアシュリー。コードが実行されるコンテキストを知らなくても、パフォーマンスが問題になるかどうかを判断することは不可能です。ランタイム環境が最大限の効率を必要としているのでなければ、私はいつもDRYを使い始めます。テストが許容できないパフォーマンスを示した場合、私は意図的にスピードを改善するためにDRYに違反します。 –

+0

私は、要素シェル( 'button'または' a')とコンテンツの分割を必要としない、これを達成するためにあまり「冗長」な方法を望んでいました。なぜなら、コンテンツは "独立しているため、実際には分離されたコンポーネントである必要はありません。 – suamikim

1

ギッターを見ながら申し訳ありませんが、私は一度に2つのことをやっていた、私は明らかに:-)

で良くない午前:dがこの一つのファイルであります

最終的に成し遂げたかったことは、これも可能でしょうか?

私はa11yの専門家ではない、またはその領域に関する多くの知識を持っていますが、私が理解していることから、これはあなたが望むものを達成します。ブラウザはrole属性を見てリンクやボタンとして扱い、実際の要素の型自体を無視します。ボタンやアンカーであれば、roleに定義されている型と同じように動作します。

ボタンやリンクタグのようにCSSでスタイルを設定できます。タイプがリンクまたはボタンのどちらかである

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

、この参照してください。それは(isLinkBtn` `のような)ビューモデルのプロパティにアクセスすることはできませんので、https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_link_role

+0

これはうまくいくと思うし、なぜ私が実際に論じることはできないが、可能な限り意味的に正しいタグを明示的に使用することを好むだろう。私は正しいタグ(例えば 'divsやその他のもので構成されたカスタム'コンボボックス ')を技術的に使用することができない状況で 'ロール'を使用したいと思います。いずれにせよ提案のおかげで! – suamikim

関連する問題