vuejs2vue-componentlaravel-5.7vue-filter

Hide Card Elements in Vue


I've got a little question on how to do something like that: I have 2 components (one for a Sidebar and one for my Cards (Bootstrap Cards)) The cards component gets rendered within a foreach loop directly from the database. There are 3 attributes: title, description and category. Right now I want the sidebar to filter through that category and display all or only one category dynamically via Vue. But I really don't know how. I'm new to Vue. I think I should use a onclick method but how to look for the right directory.

welcome.blade.php

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    @include('includes.header')
    <body>
        <div id="app" class="wrapper">
            @include('includes.nav')
            @include('includes.headerPicture')
            <!--@include('includes.headerSidebar')-->
            <cards></<cards>
            @include('includes.footer')
        </div>
        <script src="/js/app.js"></script>
    </body>
</html>

And the CardComponent

<template>
    <div class="container">
        <div class="row">
            <div class="container sidebar-container">
            <ul class="nav justify-content-center nav-tabs">
                <li class="nav-item">
                    <a class="nav-link" href="/" style="color:white">Alle</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="/livingspaces" style="color:white">Wohnraum</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="/therapies" style="color:white">Therapien</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="/news" style="color:white">News</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="/achievements" style="color:white">Erfolge</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="/events" style="color:white">Events</a>
                </li>
            </ul>
            </div>
            <div class="card" style="width: 18rem;" v-for="card in cards">
            <img src="/img/card2.jpg" class="card-img-top">
                <div class="card-body">
                    <h5 class="card-title">{{card.title}}</h5>
                    <p class="card-text">{{card.text}}</p>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
export default {
    data() {
        return {
            card: {
                title: '',
                description: '',
                category: '',
                text: ''
            },
            cards: [],
            validationErrors: '',
            uri: 'http://localhost:8000/cards/',
            isHidden: true
        }
    },

    methods: {
        loadCards() {
            axios.get(this.uri).then(response=>{
                this.cards = response.data.sortedData;
                this.loading=true;
            })
        }
    },
    mounted() {
        this.loadCards();
    }
}
</script>
<style>
.sidebar-container {
    padding-bottom: 2em;
}
</style>

JSON Data:

{
sortedData: [
{
id: 1,
title: "Test2222",
description: "Test",
text: "Test",
category: "achievement",
created_at: "2019-01-17 15:56:14",
updated_at: "2019-01-25 12:25:26"
},
{
id: 2,
title: "TestView",
description: "asd",
text: "asd",
category: "achievements",
created_at: "2019-01-18 12:06:40",
updated_at: "2019-01-18 12:06:40"
},
{
id: 1,
title: "Test",
description: "Test",
text: "Testr",
category: "news",
created_at: "2019-01-16 16:05:51",
updated_at: "2019-01-16 16:05:51"
},
{
id: 1,
title: "Test",
description: "Test",
text: "Test",
category: "livingspaces",
created_at: "2019-01-16 16:31:53",
updated_at: "2019-01-16 16:31:53"
},
{
id: 2,
title: "Test",
description: "Test",
text: "Test",
category: "livingspaces",
created_at: "2019-01-17 15:55:48",
updated_at: "2019-01-17 15:55:48"
},
{
id: 3,
title: "Test",
description: "asdsadsadsadsadsdsdsadasdasdasdsadasdadsadsadasdsasadasdsadsadasdsads",
text: "Tesst",
category: "achievement",
created_at: "2019-01-28 15:15:20",
updated_at: "2019-01-28 15:15:20"
},
{
id: 1,
title: "Test",
description: "Test",
text: "Test",
category: "events",
created_at: "2019-01-16 16:43:05",
updated_at: "2019-01-16 16:43:05"
},
{
id: 1,
title: "Test",
description: "Test",
text: "Test",
category: "therapien",
created_at: "2019-01-16 16:42:35",
updated_at: "2019-01-16 16:42:35"
},
{
id: 2,
title: "TestFinal",
description: "Test",
text: "Test",
category: "therapies",
created_at: "2019-01-18 12:20:17",
updated_at: "2019-01-18 12:20:17"
}
]
}

Could you give me a hint or a little example on how to do something like that?


Solution

  • You need to bring your app.js code in the blade file otherwise you can't access the data fields. Once you get your app.js code, create a data field sCat: ''. Then in your card-component use an if statement to see if the current category is equal to the sCat or sCat is equal to null. For ex:

    <card-component title={{$data->title}} description={{$data->description}} category={{$data->category}} v-if="(sCat == {{$data->category}} || sCat === '')"></card-component>
    

    A better approach would be to create a master component and put everything you have under the id="app" div, in the master component. This way you will have better control of your vue codes.

    EDIT

    Approach 1:

    <!doctype html>
    <html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    @include('includes.header')
    <body>
        <div id="app" class="wrapper">
            <nav-component></nav-component>
            <header-component></header-component>
            <header-sidebar-component></header-sidebar-component>
                <div class = "container">
                <div class="row">
                @foreach ($sortedData as $data)
                        <card-component title={{$data->title}} description={{$data->description}} category={{$data->category}}></card-component v-if="(sCat == {{$data->category}} || sCat === '')">
                @endforeach
                </div>
                </div>
        </div>
        <script src="/js/app.js"></script>
        //Move your vue instance from app.js to here as below
        <script>
            new Vue({
                el: "#app",
                data: {
                    sCat: '',
                    ...
                }
                ....
            });
        </script
    </body>
    </html>
    

    Approach 2 (recommended):

    welcome.blade.php

    <!doctype html>
    <html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    @include('includes.header')
    <body>
        <div id="app" class="wrapper">
            <master card-items="{{ $data }}">
        </div>
        <script src="/js/app.js"></script>
    </body>
    </html>
    

    Master.vue

    template
        <nav-component></nav-component>
        <header-component></header-component>
        <header-sidebar-component></header-sidebar-component>
        <div class = "container">
            <div class="row">
                <div class="col-x-y" v-for="item in items"> //add some column values if needed or use plain div
                    <card-component :title="item->title" :description="item->description" :category="item->category" v-show="(sCat === item->category || sCat === '')"></card-component>
            </div>
        </div>
    script
        import NavComponent from 'pathToNavComponent.js';
        //import other components
        props: {
            items: Array
        }
        components: {
            NavComponent,
            ... //other components imported
        }
        data: {
            sCat: '',
            ...
        }
        ...