[Vuejs]-How do I switch between a template using a Grid Layout and another using Flex depending on what is supported by the browser dynamically?

0👍

I think I got it, need 2 make 2 separate components, one with a flex and one with the css grid as the structure, cannot have both in one component because the structural layout of the item is different using css grid and flexbox, make a 3rd component that checks for support of CSS Grid in JS using a computed property CSS.supports(‘display’, ‘grid’)

HTML

script#flex(type="text/x-template")
    .news-item2(
        :key="item.feed_item_id",
        :ref="item.feed_item_id",
        role="listitem",
        tabindex="0"
    )
        .news-item-pubdate-wrapper
            .news-item-pubdate2 1m  
        .news-item-content-wrapper
            .news-item-title-wrapper
                .news-item-title2(:style="titleStyle") {{ item.title }}
                    span.news-item-link2  example.com
            .news-item-votes-wrapper
                .news-item-likes2
                    span.icon.is-small.news-item-vote-icon2
                        i.fa.fa-xs.fa-thumbs-up
                    span.news-item-vote-count2 {{ item.likes }}
                .news-item-dislikes2
                    span.icon.is-small.news-item-vote-icon2
                        i.fa.fa-xs.fa-thumbs-down
                    span.news-item-vote-count2 {{ item.dislikes }}
                .news-item-bullish2
                    span.icon.is-small.news-item-vote-icon2
                        i.fa.fa-xs.fa-arrow-up
                    span.news-item-vote-count2 {{ item.bullish }}
                .news-item-bearish2
                    span.icon.is-small.news-item-vote-icon2
                        i.fa.fa-xs.fa-arrow-down
                    span.news-item-vote-count2 {{ item.bearish }}
                .news-item-comments2
                    span.icon.is-small.news-item-vote-icon2
                        i.fa.fa-xs.fa-comment-alt
                    span.news-item-vote-count2 0
        .news-item-tags-wrapper
            .news-item-tags2.has-text-right(:style="tagStyle")
                .news-item-tag2(
                    v-for="(tag, i) in item.tags",
                    :key="item.tag",
                    @click.stop="updateTag(tag)"
                )
                    a.button.is-paddingless.is-small.is-uppercase.is-text
                        | {{ tag }}
                        span(v-if="lineCountTag - 1 === i && item.tags.length > lineCountTag") ...
                        span(v-else)    

script#grid(type="text/x-template")
    .news-item(
        :key="item.feed_item_id",
        :ref="item.feed_item_id",
        role="listitem",
        tabindex="0"
    )
        .news-item-pubdate 1m 
        .news-item-title(:style="titleStyle") {{ item.title }}
            span.news-item-link  example.com
        .news-item-likes
            span.icon.is-small.news-item-vote-icon
                i.fa.fa-xs.fa-thumbs-up
            span.news-item-vote-count {{ item.likes }}
        .news-item-dislikes
            span.icon.is-small.news-item-vote-icon
                i.fa.fa-xs.fa-thumbs-down
            span.news-item-vote-count {{ item.dislikes }}
        .news-item-bullish
            span.icon.is-small.news-item-vote-icon
                i.fa.fa-xs.fa-arrow-up
            span.news-item-vote-count {{ item.bullish }}
        .news-item-bearish
            span.icon.is-small.news-item-vote-icon
                i.fa.fa-xs.fa-arrow-down
            span.news-item-vote-count {{ item.bearish }}
        .news-item-comments
            span.icon.is-small.news-item-vote-icon
                i.fa.fa-xs.fa-comment-alt
            span.news-item-vote-count 0
        .news-item-tags.has-text-right(:style="tagStyle")
            .news-item-tag(
                v-for="(tag, i) in item.tags",
                :key="item.tag",
                @click.stop="updateTag(tag)"
            )
                a.button.is-paddingless.is-small.is-uppercase.is-text
                    | {{ tag }}
                    span(v-if="lineCountTag - 1 === i && item.tags.length > lineCountTag") ...
                    span(v-else)    

script#item(type="text/x-template")
    template(v-if="supportsCssGrid", :item="item")
        grid(:item="item")
    template(v-else)
        flex(:item="item")

body
    #__nuxt
        #__layout
            item(:item="item")

Vue JS

const lineClamp = {
    data() {
        return {
            lineCountTag: 2,
            lineCountTitle: 2,
            heightPerLineTag: 30,
            heightPerLineTitle: 24
        };
    },
    computed: {
        tagStyle() {
            return {
                height: this.heightPerLineTag * this.lineCountTag + "px",
                maxHeight: this.heightPerLineTag * this.lineCountTag + "px"
            };
        },
        titleStyle() {
            return {
                height: this.heightPerLineTitle * this.lineCountTitle + "px",
                maxHeight: this.heightPerLineTitle * this.lineCountTitle + "px"
            };
        }
    }
};

Vue.component("flex", {
    template: "#flex",
    mixins: [lineClamp],
    props: {
        item: {
            type: Object,
            default: () => {},
            required: true
        }
    }
});

Vue.component("grid", {
    template: "#grid",
    mixins: [lineClamp],
    props: {
        item: {
            type: Object,
            default: () => {},
            required: true
        }
    }
});

Vue.component("item", {
    template: "#item",
    props: {
        item: {
            type: Object,
            default: () => {},
            required: true
        }
    },
    computed: {
        supportsCssGrid() {
            return CSS.supports("display", "grid");
        }
    }
});

new Vue({
    el: "#__nuxt",
    data() {
        return {
            item: {
                feed_item_id: 1,
                title:
                    "The first one is made with a grid layout while the second one is made with a flex layout. The templates are different, how do I load the right one based on what is supported by the browser?",
                tags: ["trump", "putin", "defi"],
                likes: 10,
                dislikes: 5,
                bullish: 6,
                bearish: 0
            },
            lineCountTag: 2,
            lineCountTitle: 2,
            heightPerLineTag: 30,
            heightPerLineTitle: 24
        };
    },
    computed: {
        tagStyle() {
            return {
                height: this.heightPerLineTag * this.lineCountTag + "px",
                maxHeight: this.heightPerLineTag * this.lineCountTag + "px"
            };
        },
        titleStyle() {
            return {
                height: this.heightPerLineTitle * this.lineCountTitle + "px",
                maxHeight: this.heightPerLineTitle * this.lineCountTitle + "px"
            };
        }
    }
});

Leave a comment