Vue v-bind和AJAX

I'm trying to move away from jQuery towards Vue 2.0, which for the most part the transition has felt very easy.

However, when making AJAX calls and interacting with the response I'm approaching it wrong and I can't get into the Vue mindset of doing things.

For example, I have a "Modal trigger" which when clicked opens a modal window and makes an AJAX call to a href which is bound to the trigger and then returns the the html to v-html in the modal. My problem comes when I want to have an @click event in the modal, obviously it doesn't work because Vue hasn't registered it, which makes sense.

In jQuery where I could just say for example $(document).on('click'... so that it could recognise any AJAX loaded pages, I cannot work out a similar option in Vue, I'm clearly approaching the situation wrong.

I've spent hours searching for a solution and I'm no further forward, could anyone with experience of similar situations please let me know how they overcame their issues or point me in the direction of tutorials that deal with similar problems.

Thank you in advance.

You need conditional rendering. And the point is, template is not conditional, data is. So the @click is actually always in your template, but with the data changes, you have different views, even different user interaction behaviours in your view.

  • you want a button, but only when some condition flag is true, so in the data option, flag is false initially, but you load the real status from server via an AJAX call, which may set flag to true so the button shows. Template may be like <button v-if="flag" @click="clicked"></button>

  • you want a button, always, but clicking it doesn't always do something(e.g. show an alert), so you have <button @click="clicked"></button>, and if(this.flag) {/*do something*/} in clicked, while flag is loaded by AJAX like above.

I believe I have found a good solution to my issue by using "Dynamic components" - I have built a basic example which loads in different components based on a button click, makes an AJAX call to a php script to update the alert message the new components button fires.

Here is my Code:

script.js

Vue.component('foo', {
  'template' : '<button @click="aFooButton()">This is a foo button</button>',

  data() {
    return {

    }
  },

  methods: {

    aFooButton() {
      alert(this.$parent.componentData);
    }

  }
})



Vue.component('bar', {
  'template' : '<button @click="aBarButton()">This is a bar button</button>',

  data() {
    return {

    }
  },

  methods: {

    aBarButton() {
      alert(this.$parent.componentData);
    }

  }
})



new Vue({
  el : "#root",

  data : {
    component: null,
    componentData: null
  },

  methods : {

    makeFoo() {
      axios.get('ajax/foo.php').then(response => this.componentData = response.data);
      this.component = 'foo';
    },

    makeBar() {
      axios.get('ajax/bar.php').then(response => this.componentData = response.data);
      this.component = 'bar';
    }

  },

  mounted() {

  }


})



Vue.component('bar', {
  'template' : '<button @click="aBarButton()">This is a bar button</button>',

  data() {
    return {

    }
  },

  methods: {

    aBarButton() {
      alert(this.$parent.componentData);
    }

  }
})



new Vue({
  el : "#root",

  data : {
    component: null,
    componentData: null
  },

  methods : {

    makeFoo() {
      axios.get('ajax/foo.php').then(response => this.componentData = response.data);
      this.component = 'foo';
    },

    makeBar() {
      axios.get('ajax/bar.php').then(response => this.componentData = response.data);
      this.component = 'bar';
    }

  },

  mounted() {

  }


})

index.html

<!DOCTYPE html>

<html lang="en">
<head>
  <meta charset="utf-8">

  <title>Vue</title>

</head>

<body id="app">

  <div id="root" class="container">

      <div>
          <component :is="component"></component>
      </div>

      <div>
          <button @click="makeFoo()">Make foo</button>
          <button @click="makeBar()">Make bar</button>
      </div>

  </div>



  <script src="ajax/javascript/vue.js"></script>
  <script src="ajax/javascript/axios.js"></script>
  <script src="ajax/javascript/script.js"></script>
</body>
</html>

foo.php

<?php
  header('Content-Type: application/json');
  echo json_encode('This is some Foo information');
 ?>

bar.php

<?php
  header('Content-Type: application/json');
  echo json_encode('This is some Bar information');
 ?>

This appears to me to be a good solution, can anyone tell me if there's any reason I should not tackle my issue using this approach?

(Please note this is a basic example, I would usually have my components in separate files etc)

Thanks in advance

EDIT:

Reading further I have discovered "Vue Router" which seems to offer a similar solution to what I have achieved above - Does anyone have any experience with this and is it a better option?

EDIT 2:

I decided to recreate the above using Vue Router, the code for anyone interested is:

index.html

<!DOCTYPE html>

<html lang="en">
<head>
  <meta charset="utf-8">

  <title>Vue</title>


</head>

<body id="app">

  <div id="root" class="container">

    <div>
        <router-link to="/foo">Go to Foo</router-link>
        <router-link to="/bar">Go to Bar</router-link>
    </div>

    <div>
        <router-view></router-view>
    </div>

  </div>



  <script src="router/javascript/vue.js"></script>
  <script src="router/javascript/router.js"></script>
  <script src="router/javascript/axios.js"></script>
  <script src="router/javascript/script.js"></script>
</body>
</html>

script.js

const Foo = Vue.component('foo', {
  'template' : '<button @click="aFooButton()">This is a foo button</button>',

  data() {
    return {

      loading: false,
      message: null,
      error: null

    }
  },

  created () {
    // fetch the data when the view is created and the data is
    // already being observed
    this.fetchData()
  },
  watch: {
    // call again the method if the route changes
    '$route': 'fetchData'
  },

  methods: {

    fetchData () {
      this.error = this.post = null
      this.loading = true

      axios.get('async-ajax/foo.php').then((response) => {
        this.message = response.data;
      });

    },

    aFooButton() {
      alert(this.message);
    }


  }

})



const Bar = Vue.component('bar', {
  'template' : '<button @click="aBarButton()">This is a bar button</button>',

  data() {
    return {

      loading: false,
      message: null,
      error: null

    }
  },

  created () {
    // fetch the data when the view is created and the data is
    // already being observed
    this.fetchData()
  },
  watch: {
    // call again the method if the route changes
    '$route': 'fetchData'
  },

  methods: {

    fetchData () {
      this.error = this.post = null
      this.loading = true

      axios.get('async-ajax/bar.php').then((response) => {
        this.message = response.data;
      });

    },

    aBarButton() {
      alert(this.message);
    }


  }


})

const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]

const router = new VueRouter({
  routes: routes
})

new Vue({
  el : "#root",

  router: router,


})

In my experience Vue Router is better for single page applications, it updates the URL in your browser etc where as I feel Dynamic Components suits my personal needs more. I'd be interested to hear other peoples opinions and experiences.