MichaelB
MichaelB

Reputation: 1132

Vue and axios make request and display result

I am trying to set up a vue app that makes a request to a backend and then displays the result on the page. I cooked up this example

new Vue({
    data: {
        message: '{}'
    },
    el: '.login-app',
});

Vue.component('message-section', {
    template: '<div>Message Section</div>'
});

Vue.component('login-component', {
    template: '<div><button v-on:click="login(\'[email protected]\', \'passwd\')">Login</button></div>',
    methods: {
        login: function (username, password) {
            axios.post("http://192.168.1.10:8080/login", {username: username, password: password})
                .then(response => {this.message = response.data})
        }
    }
});

and an index like:

<!DOCTYPE html>

<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Vue Test</title>
  </head>
  <body>
    <div class="login-app">
      {{ message }}
      <message-section></message-section>
      <login-component></login-component>
    </div>
    <script src="/static/testvue.bundle.js"></script>
  </body>
</html>

The idea being a simple app that should send a username/password and get back something like "success" or whatever that it can display. But I am completely unfamiliar with vue and javascript so I am getting stuck. I am not sure how to make the response show up anywhere. I have a {{ message }} in there but it doesn't do anything. All I see is the {} from the "message" attribute of the Vue object getting rendered in I guess. And those user/pass is hard coded... I am not sure how to make it work with a form field.

I can see the data getting sent to the backend though so I know that's working...

Additionally, how can you structure a Vue project so it's broken into multiple "modules" or whatever?

Edit:

If I change it so there's only one component like so:

new Vue({
    data: {
        message: '{}'
    },
    el: '.login-app',
    methods: {
        login: function (username, password) {
            axios.post("http://192.168.91.30:8080/login", {username: username, password: password})
                .then(response => {this.message = response.data})
        }
    }

})

and

<div class="login-app">
  {{ message }}
  <button v-on:click="login(\'[email protected]\', \'passwd\')">Login</button>
</div>

Then nothing renders at all... This should have put them inside the same container or whatever, right?

Upvotes: 2

Views: 18353

Answers (2)

kevguy
kevguy

Reputation: 4438

The problem is your component login-component doesn't have access to the message property, which belongs to the root Vue app.

One way to fix this is simply put the message to the component instead:

Vue.component('login-component', {
  template: '<div><button v-on:click="login(\'[email protected]\', \'passwd\')">Login</button></div>',
  data() { 
    return { message: '' }
  },
  methods: {
    login: function (username, password) {
      axios.post("http://192.168.1.10:8080/login", {username: username, password: password})
        .then(response => {this.message = response.data})
      }
    }
});

But if message is not a property that you login-component to have solely access to, you may have to consider Vuex or emitting custom events (this and this).

Upvotes: 1

Bert
Bert

Reputation: 82439

Here is your edited code working.

console.clear()

new Vue({
  data: {
    message: '{}'
  },
  el: '#login-app',
  methods: {
    login: function(username, password) {
      axios.post("https://httpbin.org/post", {username, password})
        .then(response => this.message = response.data.json)
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.17.1/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.11/vue.min.js"></script>

<div id="login-app">
  {{ message }}
  <button v-on:click="login('[email protected]', 'passwd')">Login</button>
</div>

Here it is working from a component.

console.clear()

Vue.component('login-component', {
  template: `
    <div>
      <button v-on:click="login('[email protected]', 'passwd')">Login</button>
    </div>`,
  methods: {
    login: function(username, password) {
      axios.post("https://httpbin.org/post", {username, password})
        .then(response => this.$emit('login-success', response.data.json))
    }
  }
});

new Vue({
  data: {
    message: '{}'
  },
  el: '#login-app',
  methods: {
    onSuccess(message) { this.message = message }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.17.1/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.11/vue.min.js"></script>

<div id="login-app">
  {{ message }}
  <login-component @login-success="onSuccess"></login-component>
</div>

In this second example, note that message is a data property of the parent; the root Vue. The login-component does not have direct access to message. That being the case, if the ajax call is made in the component, in order to set message the value has to be emitted from the component. The code does that by emitting the custom event, login-success with the success value passed as a parameter. The parent listens for that event with the following syntax:

<login-component @login-success="onSuccess"></login-component>

Upvotes: 4

Related Questions