Answers.Body: <p>I have it working like this:</p>
  
  <p>First set axios defaults to</p>
  
  <pre><code>window.axios.defaults.headers.common = {
      'X-Requested-With': 'XMLHttpRequest'
  };
  </code></pre>
  
  <p>Then in your component I use <a href="https://www.npmjs.com/package/axios#using-applicationx-www-form-urlencoded-format" rel="nofollow noreferrer">URLSearchParams()</a> to convert object to encoded url.</p>
  
  <p>For example my user login method might look like this:</p>
  
  <pre><code>methods: {
      login() {
          var params = new URLSearchParams();
          params.append(window.csrfTokenName, window.csrfTokenValue);
          // The rest of the required fields for user login
          // add the axios.post('/', params) call bellow
      }
  }
  </code></pre>
  
  <p>The token stuff is just coming from my _layout.html file</p>
  
  <pre><code>&lt;script type="text/javascript"&gt;
      window.csrfTokenName = "{{ craft.config.csrfTokenName|e('js') }}";
      window.csrfTokenValue = "{{ craft.request.csrfToken|e('js') }}";
  &lt;/script&gt;
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-19T20:08:09.587Z
Answers.LastActivityDate: 2017-10-19T20:08:09.587Z
Answers.UserDisplayName: Vadim Goncharov
Answers.Body: <p>Perhaps it could be a issue with twig also uses the mustaches {{}} <br /><br />
  Have a look at this blog post by Andrew Welch. <br />
  (he is setting up different delimiters for Vue) <br />
  <a href="https://nystudio107.com/blog/using-vuejs-2-0-with-craft-cms" rel="nofollow noreferrer">https://nystudio107.com/blog/using-vuejs-2-0-with-craft-cms</a></p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-02-19T14:17:59.933Z
Answers.Text: Thank you @bomanden - I am using different delimiters for my output `delimiters: ['@{', '}'],` and the twig tags are being parsed in the Vue template no problem as I can see my test in the data in the Vue console. I am pretty sure its down to how I am passing the data to Craft.
Answers.UserDisplayName: Gareth
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-02-19T14:22:22.047Z
Answers.Text: Sorry , just saw that you are actually doing that already. 
  I'll hold on to the post, want to know the answer as well.
Answers.UserDisplayName: bomanden
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-02-19T14:12:47.577Z
Answers.LastActivityDate: 2017-02-19T14:12:47.577Z
Answers.UserDisplayName: bomanden
Answers.Body: <p>I got this working after some tinkering. There was no one example I could find to help clear this up so hopefully mine will be useful to others. This is using <strong>Vue</strong>, <strong>Axios</strong>, and the <strong>Guest Entries</strong> plugin, but I had to also use the <strong><a href="https://www.npmjs.com/package/qs" rel="nofollow noreferrer">qs</a></strong> stringifying library to avoid getting a <code>400</code> error. </p>
  
  <p>I avoided the <code>Using application/x-www-form-urlencoded format</code> mentioned above because <code>URLSearchParams</code> isn't fully supported yet, as explained in the <a href="https://www.npmjs.com/package/axios#using-applicationx-www-form-urlencoded-format" rel="nofollow noreferrer">Axios docs</a>. Instead, those docs suggest using <code>qs</code> as an alternative but I learned that's <a href="https://github.com/ljharb/qs/issues/239#issuecomment-352597267" rel="nofollow noreferrer">only when you're bundling it</a>. My setup required me to use <code>Qs</code> (with a capital Q).</p>
  
  <pre><code>new Vue({
      el: '#app',
      delimiters: ['[[', ']]'],
      data() {
          return {
              contactForm: {
                  firstName: '',
                  lastName: '',
                  email: '',
                  message: ''
              }
          }
      },
      methods: {
          onContactFormSubmit(event) {
  
              // prep the form data
              let data = {
                  fields: this.contactForm,
                  sectionUid: 'xxxxxx-for-guest-entries-plugin'
              };
  
              // add csrf token
              data[window.csrfTokenName] = window.csrfTokenValue;
  
              // stringify data. Notice the capital Q; you may need this to be lowercase
              let dataString = Qs.stringify(data);
  
              // add yer headers
              let config = {
                  headers: {
                      'X-Requested-With': 'XMLHttpRequest',
                      'Accept': 'application/json'
                  }
              };
  
              // post it
              axios.post('/actions/guest-entries/save', dataString, config)
              .then(function (response) {
                  console.log(response);
              })
              .catch(function (error) {
                  console.log(error);
              });
          }
      }
  });
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-06-21T01:16:39.877Z
Answers.LastActivityDate: 2019-06-21T01:16:39.877Z
Answers.UserDisplayName: Ryan
Answers.Body: <p>I have it working with axios. You have to set this header in the config array: 'X-Requested-With': 'XMLHttpRequest' ;</p>
  
  <pre><code>var config = {
         responseType: 'json',
         headers: {'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded'}
      };
  </code></pre>
  
  <p>If you look at craft's getIsAjaxRequest()</p>
  
  <pre><code>public function getIsAjaxRequest()
  {
      return isset($_SERVER['HTTP_X_REQUESTED_WITH']) &amp;&amp; $_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest';
  }
  </code></pre>
  
  <p>It's looking for the X_REQUESTED_WITH header and for it to be set XMLHttpRequest.</p>
  
  <p>On top of that you have to tell Axios to send the data as application/x-www-form-urlencoded. <a href="https://www.npmjs.com/package/axios#using-applicationx-www-form-urlencoded-format" rel="nofollow noreferrer">https://www.npmjs.com/package/axios#using-applicationx-www-form-urlencoded-format</a></p>
  
  <p>I used the URLSearchParams solution.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-08-04T19:07:50.067Z
Answers.LastActivityDate: 2017-08-04T23:19:27.197Z
Answers.LastEditDate: 2017-08-04T23:19:27.197Z
Answers.UserDisplayName: NdW
Answers.Body: <p>Unlike Vue Resourse (if you've used it), Axios does not have a good way to <strong>emulateJSON</strong> on legacy servers or frameworks that do not understand submissions sent as <strong>application/json</strong>. Your data gets to Craft but it is not understood, leaving <strong>POST</strong> empty. You would need to have Axios submit to your own controller, where you can read the raw data, JSON decode it, and update the user profile with that data. Alternatively, you can tell Axios to send the data as <strong>application/x-www-form-urlencoded</strong> (<a href="https://www.npmjs.com/package/axios#using-applicationx-www-form-urlencoded-format" rel="nofollow noreferrer">https://www.npmjs.com/package/axios#using-applicationx-www-form-urlencoded-format</a>) data. However, you'll still need to read the data and decode it yourself because Axios still sends the data as a JSON string rather than form fields.</p>
  
  <p>CSRF token validation fails for the same reason.</p>
  
  <p>As a quick solution, I'd use vue resource with <code>emulateJSON</code> and <code>emulateHTTP</code> set to <code>true</code>. Integrates well with Vue and its API is very similar to Axios. Of course, once you figure out Axios, you can easily swap it out.</p>
  
  <p>If you implement your own controller action to update the user, I believe you should access the data sent by Axios with <code>craft()-&gt;request-&gt;getRawBody()</code> and then decode it into an array with <code>JsonHelper::decode()</code>.</p>
  
  <p><strong>Update:</strong> As of Craft 3.3 you can submit JSON requests to any Craft controllers, as long as they contain a <code>Content-Type: application/json</code> header.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-02-19T14:28:34.840Z
Answers.Text: Thanks Selvin, I knew you would have this one covered :-) I'll give Vue resource a try and report back here. Once I get thinks working I might well dive into Axios and try my own controller but baby steps for me work well.
Answers.UserDisplayName: Gareth
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-02-19T14:31:07.093Z
Answers.Text: That's a good plan 
Answers.UserDisplayName: Selvin Ortiz
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2017-02-19T14:23:50.030Z
Answers.LastActivityDate: 2019-09-03T20:38:35.713Z
Answers.LastEditDate: 2019-09-03T20:38:35.713Z
Answers.UserDisplayName: Selvin Ortiz
Body: <p>I currently have a working profile update form using purely craft but I would like to now enhance that using Vue and Axios to update via Ajax. I may well submit a couple of questions rather than put them all in one to try and help others. For now my main two issues are:</p>
  
  <ul>
  <li>Craft doesn't seem to like how I am supplying the CSRF so I have set it to false for now to test but I need that working.</li>
  <li>When I submit the form with with CSRF set to false in my config I get a 200 success response but the user is not updated.</li>
  </ul>
  
  <p>I suspect in both cases I am just misunderstanding how Craft expects to see the data sent, here is my code (simplified to one form field for now).</p>
  
  <pre class="lang-html prettyprint-override"><code>&lt;form method="post" action="" accept-charset="UTF-8" @submit.prevent="submitForm"&gt;
    {{ getCsrfInput() }}
    &lt;input type="hidden" name="action" value="users/saveUser"&gt;
    &lt;input type="hidden" name="redirect" value="members/profile/{% include '_includes/helpers/user_profile_link' %}"&gt;
    &lt;input type="hidden" name="userId" value="{{ currentUser.id }}"&gt;
  
    &lt;div class="control"&gt;
      &lt;label for="first-name" class="label"&gt;First Name&lt;/label&gt;
      &lt;input id="first-name" class="input" type="text" name="firstName" value="" v-model="user.firstName"&gt;
    &lt;/div&gt;
  
    &lt;button type="submit" class="button is-primary"&gt;Save Profile&lt;/button&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p>Here is my Vue.js code, I have a div with an id of <code>app</code> around the whole form and Vue is working as it should with the model binding:</p>
  
  <pre class="lang-js prettyprint-override"><code>var app = new Vue({
    delimiters: ['@{', '}'],
    el: '#app',
    data: {
      user: {
        firstName: '{{ currentUser.firstName }}'
      }
    },
    methods: {
      submitForm: function () {
  
        var config = {
          responseType: 'json'
        };
  
        var data = this.user;
  
        data[window.csrfTokenName] = window.csrfTokenValue; // Append CSRF Token
  
        axios.post('/', data, config)
             .then(function(response) {
               console.log('saved', response, data)
             });
      }
    }
  });
  </code></pre>
  
  <p>Here is my response from the console:</p>
  
  <p><a href="https://i.sstatic.net/3CWEh.png" rel="noreferrer"><img src="https://i.sstatic.net/3CWEh.png" alt="Network headers in console"></a></p>
  
  <p>Here is my console log from the submitForm method:</p>
  
  <p><a href="https://i.sstatic.net/9Vpzp.png" rel="noreferrer"><img src="https://i.sstatic.net/9Vpzp.png" alt="Console log from submitForm method"></a></p>
  
  <p>Finally here is my craft log for the form post:</p>
  
  <pre><code>$_SERVER=array (
    'HTTP_HOST' =&gt; 'tfa.dev',
    'HTTP_CONNECTION' =&gt; 'keep-alive',
    'CONTENT_LENGTH' =&gt; '125',
    'HTTP_ACCEPT' =&gt; 'application/json, text/plain, */*',
    'HTTP_ORIGIN' =&gt; 'http://tfa.dev',
    'HTTP_USER_AGENT' =&gt; 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36',
    'CONTENT_TYPE' =&gt; 'application/json;charset=UTF-8',
    'HTTP_REFERER' =&gt; 'http://tfa.dev/members/profile/edit/gareth',
    'HTTP_ACCEPT_ENCODING' =&gt; 'gzip, deflate',
    'HTTP_ACCEPT_LANGUAGE' =&gt; 'en-US,en;q=0.8',
    'HTTP_COOKIE' =&gt; '40e5c202a55b621f12b3289f66fe4061username=0298fcd1dea0b36e656a86a889e064baf094d01cs%3A84%3A%2290509830d9f39442177d77334e3cfc3eebb72a07czoyNDoiZ2FyZXRoQGdhcmV0aHJlZGZlcm4uY29tIjs%3D%22%3B; 00b542cb70dd8d427c43ee85c4523092username=0e93371fd3c232c26316e28b35a48feadfae92b5s%3A92%3A%22d736848c422c74ac22e0fba4ab7cec817bfa3da8czoyOToidGVzdG1lbWJlcjNAZ2FyZXRocmVkZmVybi5jb20iOw%3D%3D%22%3B; CraftSessionId=f0e0cea11a268bef98340313df175698; YII_CSRF_TOKEN=c447a0d39e762b38c2e68f6aee96339a633cd654s%3A81%3A%225DGNNDo2iYd6E0FBYBehrXDGn4Ns9uMpQDE3ICPk%7C65cf935623e7404164bc9dce5ae11221666cbe32%22%3B; 00b542cb70dd8d427c43ee85c4523092=77140dec55873e6c5621e2bfb211d3fbe977eae6s%3A428%3A%2214c20ffabe93387c4b6fc93f8c7d497848337bb6YTo2OntpOjA7czoyOToidGVzdG1lbWJlcjNAZ2FyZXRocmVkZmVybi5jb20iO2k6MTtzOjMyOiI1ck50REhyMEltR2RNRDNRYkJpRnR%2BQW4xNzNuTnBmbCI7aToyO3M6MzY6ImUzOGQyNTJiLTgyYzAtNDBiZi1hYTY3LTFjY2FmMjYzN2QxYSI7aTozO2k6MDtpOjQ7czoxMjA6Ik1vemlsbGEvNS4wIChNYWNpbnRvc2g7IEludGVsIE1hYyBPUyBYIDEwXzEyXzMpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS81Ni4wLjI5MjQuODcgU2FmYXJpLzUzNy4zNiI7aTo1O2E6MDp7fX0%3D%22%3B',
    'PATH' =&gt; '/usr/bin:/bin:/usr/sbin:/sbin',
    'SERVER_SIGNATURE' =&gt; '',
    'SERVER_SOFTWARE' =&gt; 'Apache',
    'SERVER_NAME' =&gt; 'tfa.dev',
    'SERVER_ADDR' =&gt; '::1',
    'SERVER_PORT' =&gt; '80',
    'REMOTE_ADDR' =&gt; '::1',
    'DOCUMENT_ROOT' =&gt; '/Users/garethredfern/Code/tfa/public',
    'SERVER_ADMIN' =&gt; 'you@example.com',
    'SCRIPT_FILENAME' =&gt; '/Users/garethredfern/Code/tfa/public/index.php',
    'REMOTE_PORT' =&gt; '49557',
    'GATEWAY_INTERFACE' =&gt; 'CGI/1.1',
    'SERVER_PROTOCOL' =&gt; 'HTTP/1.1',
    'REQUEST_METHOD' =&gt; 'POST',
    'QUERY_STRING' =&gt; '',
    'REQUEST_URI' =&gt; '/',
    'SCRIPT_NAME' =&gt; '/index.php',
    'PHP_SELF' =&gt; '/index.php',
    'REQUEST_TIME_FLOAT' =&gt; 1487494935.3640000820159912109375,
    'REQUEST_TIME' =&gt; 1487494935,
    'argv' =&gt; 
    array (
    ),
    'argc' =&gt; 0,
  )
  </code></pre>
  
  <p>From what I can see the data is not actually going through to Craft but I am getting a success response.</p>
  
  <h2>My Working Code</h2>
  
  <p>Selvin jumped on a hangout with me to help out, the easiest solution was to work with Vue resource as Selvin has answered below but I had another couple of issues. Mainly that I wasn't passing the <code>userId</code> or the <code>action</code> which are both hidden fields in my form via ajax. So here is my final JS code which worked with the form above. I have switched to using <a href="https://github.com/pagekit/vue-resource" rel="noreferrer">vue-resource</a>.</p>
  
  <pre class="lang-js prettyprint-override"><code>Vue.http.options.emulateJSON = true;
  Vue.http.options.emulateHTTP = true;
  
  var app = new Vue({
    delimiters: ['@{', '}'],
    el: '#app',
    data: {
      user: {
        firstName: '',
        userId: '{{ currentUser.id }}',
        action: 'users/saveUser'
      }
    },
    methods: {
      submitForm: function () {
  
        var data = this.user;
  
        data[window.csrfTokenName] = window.csrfTokenValue; // Append CSRF Token
  
        this.$http.post('/', data)
          .then(function(response) {
            console.log('saved', response);
          });
      }
    }
  });
  </code></pre>
  
Tags: <ajax><frontend><user-profile>
Title: Updating a user on the front end with Vue.js and Axios
ThreadText: # Updating a user on the front end with Vue.js and Axios
  
  (Asked by: username_0 on 2017-02-19)
  
  I currently have a working profile update form using purely craft but I would like to now enhance that using Vue and Axios to update via Ajax. I may well submit a couple of questions rather than put them all in one to try and help others. For now my main two issues are:
  
  * Craft doesn't seem to like how I am supplying the CSRF so I have set it to false for now to test but I need that working.
  * When I submit the form with with CSRF set to false in my config I get a 200 success response but the user is not updated.
  
  I suspect in both cases I am just misunderstanding how Craft expects to see the data sent, here is my code (simplified to one form field for now).
  
  ```html
  <form method="post" action="" accept-charset="UTF-8" @submit.prevent="submitForm">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="users/saveUser">
    <input type="hidden" name="redirect" value="members/profile/{% include '_includes/helpers/user_profile_link' %}">
    <input type="hidden" name="userId" value="{{ currentUser.id }}">
  
    <div class="control">
      <label for="first-name" class="label">First Name</label>
      <input id="first-name" class="input" type="text" name="firstName" value="" v-model="user.firstName">
    </div>
  
    <button type="submit" class="button is-primary">Save Profile</button>
  </form>
  
  ```
  
  Here is my Vue.js code, I have a div with an id of `app` around the whole form and Vue is working as it should with the model binding:
  
  ```js
  var app = new Vue({
    delimiters: ['@{', '}'],
    el: '#app',
    data: {
      user: {
        firstName: '{{ currentUser.firstName }}'
      }
    },
    methods: {
      submitForm: function () {
  
        var config = {
          responseType: 'json'
        };
  
        var data = this.user;
  
        data[window.csrfTokenName] = window.csrfTokenValue; // Append CSRF Token
  
        axios.post('/', data, config)
             .then(function(response) {
               console.log('saved', response, data)
             });
      }
    }
  });
  
  ```
  
  Here is my response from the console:
  
  [![Network headers in console](https://i.sstatic.net/3CWEh.png)](https://i.sstatic.net/3CWEh.png)
  
  Here is my console log from the submitForm method:
  
  [![Console log from submitForm method](https://i.sstatic.net/9Vpzp.png)](https://i.sstatic.net/9Vpzp.png)
  
  Finally here is my craft log for the form post:
  
  ```
  $_SERVER=array (
    'HTTP_HOST' => 'tfa.dev',
    'HTTP_CONNECTION' => 'keep-alive',
    'CONTENT_LENGTH' => '125',
    'HTTP_ACCEPT' => 'application/json, text/plain, */*',
    'HTTP_ORIGIN' => 'http://tfa.dev',
    'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36',
    'CONTENT_TYPE' => 'application/json;charset=UTF-8',
    'HTTP_REFERER' => 'http://tfa.dev/members/profile/edit/username_0',
    'HTTP_ACCEPT_ENCODING' => 'gzip, deflate',
    'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.8',
    'HTTP_COOKIE' => '40e5c202a55b621f12b3289f66fe4061username=0298fcd1dea0b36e656a86a889e064baf094d01cs%3A84%3A%2290509830d9f39442177d77334e3cfc3eebb72a07czoyNDoiZ2FyZXRoQGdhcmV0aHJlZGZlcm4uY29tIjs%3D%22%3B; 00b542cb70dd8d427c43ee85c4523092username=0e93371fd3c232c26316e28b35a48feadfae92b5s%3A92%3A%22d736848c422c74ac22e0fba4ab7cec817bfa3da8czoyOToidGVzdG1lbWJlcjNAZ2FyZXRocmVkZmVybi5jb20iOw%3D%3D%22%3B; CraftSessionId=f0e0cea11a268bef98340313df175698; YII_CSRF_TOKEN=c447a0d39e762b38c2e68f6aee96339a633cd654s%3A81%3A%225DGNNDo2iYd6E0FBYBehrXDGn4Ns9uMpQDE3ICPk%7C65cf935623e7404164bc9dce5ae11221666cbe32%22%3B; 00b542cb70dd8d427c43ee85c4523092=77140dec55873e6c5621e2bfb211d3fbe977eae6s%3A428%3A%2214c20ffabe93387c4b6fc93f8c7d497848337bb6YTo2OntpOjA7czoyOToidGVzdG1lbWJlcjNAZ2FyZXRocmVkZmVybi5jb20iO2k6MTtzOjMyOiI1ck50REhyMEltR2RNRDNRYkJpRnR%2BQW4xNzNuTnBmbCI7aToyO3M6MzY6ImUzOGQyNTJiLTgyYzAtNDBiZi1hYTY3LTFjY2FmMjYzN2QxYSI7aTozO2k6MDtpOjQ7czoxMjA6Ik1vemlsbGEvNS4wIChNYWNpbnRvc2g7IEludGVsIE1hYyBPUyBYIDEwXzEyXzMpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS81Ni4wLjI5MjQuODcgU2FmYXJpLzUzNy4zNiI7aTo1O2E6MDp7fX0%3D%22%3B',
    'PATH' => '/usr/bin:/bin:/usr/sbin:/sbin',
    'SERVER_SIGNATURE' => '',
    'SERVER_SOFTWARE' => 'Apache',
    'SERVER_NAME' => 'tfa.dev',
    'SERVER_ADDR' => '::1',
    'SERVER_PORT' => '80',
    'REMOTE_ADDR' => '::1',
    'DOCUMENT_ROOT' => '/Users/garethredfern/Code/tfa/public',
    'SERVER_ADMIN' => 'you@example.com',
    'SCRIPT_FILENAME' => '/Users/garethredfern/Code/tfa/public/index.php',
    'REMOTE_PORT' => '49557',
    'GATEWAY_INTERFACE' => 'CGI/1.1',
    'SERVER_PROTOCOL' => 'HTTP/1.1',
    'REQUEST_METHOD' => 'POST',
    'QUERY_STRING' => '',
    'REQUEST_URI' => '/',
    'SCRIPT_NAME' => '/index.php',
    'PHP_SELF' => '/index.php',
    'REQUEST_TIME_FLOAT' => 1487494935.3640000820159912109375,
    'REQUEST_TIME' => 1487494935,
    'argv' => 
    array (
    ),
    'argc' => 0,
  )
  
  ```
  
  From what I can see the data is not actually going through to Craft but I am getting a success response.
  
  ## My Working Code
  
  username_5 jumped on a hangout with me to help out, the easiest solution was to work with Vue resource as username_5 has answered below but I had another couple of issues. Mainly that I wasn't passing the `userId` or the `action` which are both hidden fields in my form via ajax. So here is my final JS code which worked with the form above. I have switched to using [vue-resource](https://github.com/pagekit/vue-resource).
  
  ```js
  Vue.http.options.emulateJSON = true;
  Vue.http.options.emulateHTTP = true;
  
  var app = new Vue({
    delimiters: ['@{', '}'],
    el: '#app',
    data: {
      user: {
        firstName: '',
        userId: '{{ currentUser.id }}',
        action: 'users/saveUser'
      }
    },
    methods: {
      submitForm: function () {
  
        var data = this.user;
  
        data[window.csrfTokenName] = window.csrfTokenValue; // Append CSRF Token
  
        this.$http.post('/', data)
          .then(function(response) {
            console.log('saved', response);
          });
      }
    }
  });
  
  ```
  
  **Tags:** ajax, frontend, user-profile
  
  
  ---
  
  ## 5 answers
  
  ### Answer by username_5 on 2017-02-19. Score: 9 | Accepted answer
  
  Unlike Vue Resourse (if you've used it), Axios does not have a good way to **emulateJSON** on legacy servers or frameworks that do not understand submissions sent as **application/json**. Your data gets to Craft but it is not understood, leaving **POST** empty. You would need to have Axios submit to your own controller, where you can read the raw data, JSON decode it, and update the user profile with that data. Alternatively, you can tell Axios to send the data as **application/x-www-form-urlencoded** (<https://www.npmjs.com/package/axios#using-applicationx-www-form-urlencoded-format>) data. However, you'll still need to read the data and decode it yourself because Axios still sends the data as a JSON string rather than form fields.
  
  CSRF token validation fails for the same reason.
  
  As a quick solution, I'd use vue resource with `emulateJSON` and `emulateHTTP` set to `true`. Integrates well with Vue and its API is very similar to Axios. Of course, once you figure out Axios, you can easily swap it out.
  
  If you implement your own controller action to update the user, I believe you should access the data sent by Axios with `craft()->request->getRawBody()` and then decode it into an array with `JsonHelper::decode()`.
  
  **Update:** As of Craft 3.3 you can submit JSON requests to any Craft controllers, as long as they contain a `Content-Type: application/json` header.
  
  > **Comments:**
  > **username_0**: Thanks username_5, I knew you would have this one covered :-) I'll give Vue resource a try and report back here. Once I get thinks working I might well dive into Axios and try my own controller but baby steps for me work well.  
  > **username_5**: That's a good plan   
  
  ---
  
  ### Answer by username_1 on 2017-10-19. Score: 2
  
  I have it working like this:
  
  First set axios defaults to
  
  ```
  window.axios.defaults.headers.common = {
      'X-Requested-With': 'XMLHttpRequest'
  };
  
  ```
  
  Then in your component I use [URLSearchParams()](https://www.npmjs.com/package/axios#using-applicationx-www-form-urlencoded-format) to convert object to encoded url.
  
  For example my user login method might look like this:
  
  ```
  methods: {
      login() {
          var params = new URLSearchParams();
          params.append(window.csrfTokenName, window.csrfTokenValue);
          // The rest of the required fields for user login
          // add the axios.post('/', params) call bellow
      }
  }
  
  ```
  
  The token stuff is just coming from my \_layout.html file
  
  ```
  <script type="text/javascript">
      window.csrfTokenName = "{{ craft.config.csrfTokenName|e('js') }}";
      window.csrfTokenValue = "{{ craft.request.csrfToken|e('js') }}";
  </script>
  
  ```
  
  
  ---
  
  ### Answer by username_2 on 2017-02-19. Score: 1
  
  Perhaps it could be a issue with twig also uses the mustaches {{}}   
    
  Have a look at this blog post by Andrew Welch.   
  (he is setting up different delimiters for Vue)   
  <https://nystudio107.com/blog/using-vuejs-2-0-with-craft-cms>
  
  > **Comments:**
  > **username_0**: Thank you @username_2 - I am using different delimiters for my output `delimiters: ['@{', '}'],` and the twig tags are being parsed in the Vue template no problem as I can see my test in the data in the Vue console. I am pretty sure its down to how I am passing the data to Craft.  
  > **username_2**: Sorry , just saw that you are actually doing that already.  I'll hold on to the post, want to know the answer as well.  
  
  ---
  
  ### Answer by username_3 on 2019-06-21. Score: 1
  
  I got this working after some tinkering. There was no one example I could find to help clear this up so hopefully mine will be useful to others. This is using **Vue**, **Axios**, and the **Guest Entries** plugin, but I had to also use the **[qs](https://www.npmjs.com/package/qs)** stringifying library to avoid getting a `400` error.
  
  I avoided the `Using application/x-www-form-urlencoded format` mentioned above because `URLSearchParams` isn't fully supported yet, as explained in the [Axios docs](https://www.npmjs.com/package/axios#using-applicationx-www-form-urlencoded-format). Instead, those docs suggest using `qs` as an alternative but I learned that's [only when you're bundling it](https://github.com/ljharb/qs/issues/239#issuecomment-352597267). My setup required me to use `Qs` (with a capital Q).
  
  ```
  new Vue({
      el: '#app',
      delimiters: ['[[', ']]'],
      data() {
          return {
              contactForm: {
                  firstName: '',
                  lastName: '',
                  email: '',
                  message: ''
              }
          }
      },
      methods: {
          onContactFormSubmit(event) {
  
              // prep the form data
              let data = {
                  fields: this.contactForm,
                  sectionUid: 'xxxxxx-for-guest-entries-plugin'
              };
  
              // add csrf token
              data[window.csrfTokenName] = window.csrfTokenValue;
  
              // stringify data. Notice the capital Q; you may need this to be lowercase
              let dataString = Qs.stringify(data);
  
              // add yer headers
              let config = {
                  headers: {
                      'X-Requested-With': 'XMLHttpRequest',
                      'Accept': 'application/json'
                  }
              };
  
              // post it
              axios.post('/actions/guest-entries/save', dataString, config)
              .then(function (response) {
                  console.log(response);
              })
              .catch(function (error) {
                  console.log(error);
              });
          }
      }
  });
  
  ```
  
  
  ---
  
  ### Answer by username_4 on 2017-08-04. Score: 1
  
  I have it working with axios. You have to set this header in the config array: 'X-Requested-With': 'XMLHttpRequest' ;
  
  ```
  var config = {
         responseType: 'json',
         headers: {'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/x-www-form-urlencoded'}
      };
  
  ```
  
  If you look at craft's getIsAjaxRequest()
  
  ```
  public function getIsAjaxRequest()
  {
      return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest';
  }
  
  ```
  
  It's looking for the X\_REQUESTED\_WITH header and for it to be set XMLHttpRequest.
  
  On top of that you have to tell Axios to send the data as application/x-www-form-urlencoded. <https://www.npmjs.com/package/axios#using-applicationx-www-form-urlencoded-format>
  
  I used the URLSearchParams solution.
  
  
  ---
  
  