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).
<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:
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:
Here is my console log from the submitForm method:
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/gareth',
'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' => '[email protected]',
'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
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 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.
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);
});
}
}
});