Greg Johnson
Greg Johnson

Reputation: 377

Limitations on polymer conditional templates?

I'm working on a set of conditional views based on the data available in a JSON object - effectively, show a media view if we have media to show, show a document view if we have merely text information to show, etc. The approach I've been using to date uses hasOwnProperty() to check the JSON object to determine the available data and work out the view template based on what's there.

I've implemented something as a barebones version of this, but now I get nothing at all. The if seems to just kill the nested templates. Here's what I'm trying:

        <template bind if="{{ posts[postid].hasOwnProperty('video') }}">

            <div class="tileHeader">Posted by @{{ posts[postid].creator_id }} <time-ago datetime="{{ posts[postid].creation_date }}"></time-ago></div>
            <div class="tile">
                <div class="heroTop" style="background-image: url({{ posts[postid].body }}) no-repeat"></div>
                <div class="heroBottom">
                    <div class="headline">{{ posts[postid].url_title }}</div>
                    <div class="postDesc">{{ posts[postid].url_description }}</div>
                </div>
                <div class="attribution">
                    {{ posts[postid].url }}
                </div>
            </div>

        </template>



        <template bind if="{{ posts[postid].hasOwnProperty('image') }}">

            <div class="tileHeader">Posted by @{{ posts[postid].creator_id }} <time-ago datetime="{{ posts[postid].creation_date }}"></time-ago></div>
            <div class="tile solo-view">
                <div class="heroSolo">
                    {{ posts[postid].body }}
                </div>
                <div class="attribution">
                    {{ posts[postid].url }}
                </div>
            </div>

        </template>

Two questions: 1. Can this if statement work in this context, or does this need to be re-built as a filter? 2. What happens in the case where both ifs are true for a given render?

Upvotes: 2

Views: 2909

Answers (2)

Quickredfox
Quickredfox

Reputation: 1466

From the documentation: https://www.polymer-project.org/docs/polymer/binding-types.html#importing-templates-by-reference

You could use the ref attribute combined with bind to make this less of a mess.

 <!-- Create Your displayType templates -->

 <template id="longArticle">
   <!-- template for displayType === longArticle -->
 </template>
 <template id="bareImage">
   <!-- template for displayType === bareImage -->
 </template>

 <!-- then construct your loop -->

 <template for={{postid in postids}}>
   <template bind ref="{{posts[postid].displaytype}}"></template>
 </template>

Upvotes: 1

Greg Johnson
Greg Johnson

Reputation: 377

Ok, this seems to be working. Is it messy? Yes, definitely. Effectively, from my API I get a slew of post_ids that I need to format differently depending on what I'm finding. Trying to use something like JSON.hasOwnProperty didn't work (don't know why) so I'm resorting to assigning a variable based on a separate discovery function.

Is there a better way to do this? Of this, I'm certain. If you've got a better approach, please do let me know. But here's what I've come to:

<template repeat="{{ postid in postids }}">
        <core-ajax id="postdetail" url="api/1/posts/{{ postid }}" data-postid="{{ postid }}" postid="{{ postid }}" handleAs="json" method="GET" auto on-core-response="{{ updatePostDetail }}"></core-ajax>

        <template if="{{ posts[postid].displaytype == 'articleImage' }}">

            <div class="tileHeader"><user-print creatorid="{{ posts[postid].creator_id }}" prepend="Posted by" size="small"></user-print> <span hidden?="{{ showchannel }}">In channel {{ posts[postid].channel_id }}</span> <time-ago prepend="Last update " isostring="{{ posts[postid].creation_date }}"></time-ago></div>
            <div class="tile media-view" style="background: url({{ posts[postid].banner }}) no-repeat; background-size: cover;" title="{{ posts[postid] | descText }}">
                <div class="heroBottom">
                    <div class="type">{{ posts[postid].displaytype }}</div>
                    <div class="headline">{{ posts[postid].url_title }}</div>
                    <div class="postDesc">{{ posts[postid].body | stripTags | shorten }}</div>
                    <div class="attribution"> {{ posts[postid].url }} </div>
                </div>
            </div>

        </template>

        <template if="{{ posts[postid].displaytype == 'video' }}">

          ... (etc)

        </template>

</template>

<script>

Polymer('post-list', {
    postids: [],
    posts: {},
    created: function(){

    },
    ready: function(){

    },
    updatePostList: function(e){
        this.postids = e.detail.response.post_ids;
    },
    updatePostDetail: function(e){
        json = e.detail.response.post;
        postid = json.id;
        this.posts[postid] = json;

        this.posts[postid].displaytype = 'barePost'; // default value so I don't have to worry about a bunch of similar 'else' statements
        this.posts[postid].hasVideo = 'noVideo'; // ditto

        if(json.hasOwnProperty('url_meta_tags')){
            if(json.url_meta_tags.hasOwnProperty('og:video') || json.url_meta_tags.hasOwnProperty('twitter:player:stream')){
                this.posts[postid].hasVideo = 'video';
                this.posts[postid].displaytype = 'video';
            }
            else if(json.url_meta_tags.hasOwnProperty('og:image') || json.url_meta_tags.hasOwnProperty('image') || json.hasOwnProperty('banner')){
                if(json.body.length > 350){
                    this.posts[postid].displaytype = 'longArticle';
                }
                else if(json.body.length > 0){
                    this.posts[postid].displaytype = 'articleImage';
                }
                else{
                    this.posts[postid].displaytype = 'bareImage';
                }
            }
        }
        else if(json.hasOwnProperty('files')){
            this.posts[postid].displaytype = 'embeddedMedia';
        }
    }

    </script>

Upvotes: 1

Related Questions