4

How can i pass a Javascript Variable to a Vue Component?

I have this jQuery function which generates the menu and pushes all the Values inside the array menu:

var menu = [];

$(document).ready(function(){
    $('.service-desc-wrap h2,.cta-button').each(function(){
        if($(this).hasClass('cta-button')) {
            if($(this).attr('title') && $(this).attr('href')) {
                var linkTitle = $(this).attr('title');
                var href = $(this).attr('href');
                data = [
                    title = linkTitle, 
                    href = href,
                ]
                menu.push(data);
                $('#menu, #menuMobile').append('<a class="menuText" href="'+href+'">'+linkTitle+'</a>')
            };
        } else {
            var tag = $.slugify($(this).text());
            $(this).attr('id',tag);
            var linkTitle = $(this).text();
            if($(this).attr('title')) {
                var linkTitle = $(this).attr('title');
            };
                data = [
                    title = linkTitle, 
                    href = tag,
                ]
                menu.push(data);
            $('#menu, #menuMobile').append('<a class="menuText" href="#'+tag+'">'+linkTitle+'</a>')
        }
    }); 
}); 

I want to pass the array to a Vue Component called

<service-menu-component></service-menu-component>

The jQuery Function and the Component are inside a blade.php file, i'm using Laravel as a backend.

0

5 Answers 5

3

Any Vue component has access to the global scope (a.k.a window object), in which $ performs. You don't have to do anything special about it. In simpler words, if a variable has been declared in global scope at the time your Vue component is created - Vue can access it. But Vue won't react to later mutations performed on the contents of that variable. Not out of the box, anyway.

In Vue, that behavior is called reactivity. If that's what you want, you could use Vue.observable():

  • declare a const, holding a reactive reference (store.menu in this example - name it to whatever makes sense to you)
  • use a computed in your Vue component, returning the reactive reference
  • at any point, (before or after Vue instance's creation) modify the reference from anywhere (including outside Vue component/instance) and the Vue instance will get the change

Proof of concept:

Vue.config.productionTip = false;
Vue.config.devtools = false;
// you don't need the above config, it just suppresses some warnings on SO

// declare store, with whatever contents you want:
const store = Vue.observable({menu: []}); 

// optionally push something to menu:
// works before Vue instance was created
store.menu.push({foo: 'bar'});

$(function() {
  // optionally push something to menu 
  // also works after Vue instance was created - i.e: 3s after $(document).ready()
  setTimeout(function() {
    store.menu.push({boo: 'far'});
  }, 3000)
})

new Vue({
  el: '#app',
  computed: {
    menu() {
      // this injects the store's menu (the reactive property) in your component
      return store.menu
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.12/vue.js"></script>
<div id="app">
  <pre v-text="menu"></pre>
</div>

The computed doesn't have to be on the root Vue element (it can be inside your <service-menu-component> component). The above is just a basic implementation, to demo the principle.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the amazing explanation, hats off to you.
0

Use props:

<service-menu-component :data=YOUR_ARRAY></service-menu-component>

In the component:

props: ['data'] // the data being passed.

1 Comment

The jQuery function and the component are inside a blade template, i can't pass data to the component like that.
0

Yes, It's possible you need to import this jQuery snippet file to your parent component, and then pass it down to your service-menu-component. Here's how the code should look like:

Your Parent.vue

<template>
    <service-menu-component :data=menu></service-menu-component>
</template>
<script src="<pathToYourJqueryFile>"></script>

And then in your service-menu-component:

<template>
   <div>
      {{ menu }}
  </div>
</template>
<script>
export default {
  name: 'service-menu-component',
  props: {
      menu: {
          type: Array
      }
  }
}
</script>

2 Comments

The jQuery function and the component are inside a blade template, i can't pass data to the component like that.
I am not sure then. I have no experience in working with laravel/blade.
0

What made it work and seemed simple after trying different things is moving the jQuery function inside the component mounted hook like this:

    mounted() {
            var menu = [];

            $(document).ready(function(){
                $('.service-desc-wrap h2,.cta-button').each(function(){
                    if($(this).hasClass('cta-button')) {
                        if($(this).attr('title') && $(this).attr('href')) {
                            var linkTitle = $(this).attr('title');
                            var href = $(this).attr('href');
                            data = {
                                'title': linkTitle, 
                                'href': href,
                            }
                            menu.push(data);
                            $('#menu, #menuMobile').append('<a class="menuText ml-2" href="'+href+'">'+linkTitle+'</a>')
                        };
                    } else {
                        var tag = $.slugify($(this).text());
                        $(this).attr('id',tag);
                        var linkTitle = $(this).text();
                        if($(this).attr('title')) {
                            var linkTitle = $(this).attr('title');
                        };
                            var data = {
                                'title': linkTitle, 
                                'href': tag,
                            }
                            menu.push(data);
                        $('#menu, #menuMobile').append('<a class="menuText ml-2" href="#'+tag+'">'+linkTitle+'</a>')
                    }
                });
                console.log(menu);
               
            }); 

             this.menu = menu;
    },

It worked like a charm.

Comments

0

@Şivam Kuvar verdiği örnekteki gibi :data='menu' yazan yeri :data="json_encode($controllerdata)" ile değiştir ve verilerini kullanmaya hazırsın. veri yapına göre @{{ data.data[0].title }} olabilir örneğin veya @{{ data.title }} bu gelen veriye bağlı dostum.

Just like @Şivam Kuvar's example, replace :data='menu' with :data="json_encode($controllerdata)" and you're ready to use your data. According to the data structure, it can be @{{ data.data[0].title }} for example or @{{ data.title }} it depends on the incoming data, my friend.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.