bernhard Posted November 12, 2020 Share Posted November 12, 2020 Hi, I'm trying to send an ajax request on my new site via UIkit's built in little JavaScript framework: https://github.com/uikit/uikit-site/blob/feature/js-utils/docs/pages/javascript-utilities.md#ajax util.ajax('/data/newsletter/', { responseType: 'json', method: 'POST', data: JSON.stringify({ mail:mail, sms:sms, msg:msg, cmt:cmt, }), }) .then(function(xhr) { console.log(xhr); if(xhr.status !== 200) { UIkit.modal.alert('error xyz'); } }); The backend throws a WireException because the form is not filled correctly and that's totally fine. try { $gg->subscribe(); } catch(Throwable $th) { http_response_code(400); die($th->getMessage()); } But I'd like to catch this error and show a message to the user. In jQuery this is easy: $.post('status.ajax.php', {deviceId: id}) .done( function(msg) { ... } ) .fail( function(xhr, textStatus, errorThrown) { alert(xhr.responseText); }); But how do I do that with the uikit framework or vanilla javascript? I've done some research and tried several try/catch variants but I always end up in the error message in the console. This is the source of the uikit ajax function: https://github.com/uikit/uikit/blob/ea4453b1a71bfebb8ac43d81757071cfc5c7cca0/src/js/util/ajax.js#L5-L62 It seems that they have thought about "network error" and "network timeout". But how do I catch them? Thx for your help ? PS I think @Tom. you are quite experienced with JS and Uikit? 1 Link to comment Share on other sites More sharing options...
kongondo Posted November 12, 2020 Share Posted November 12, 2020 1 hour ago, bernhard said: In jQuery this is easy: You will need to unlearn jQuery ?. There's a difference between an "error" and an "exception". I am guessing uikit is probably using fetch() internally? If using vanilla JS... TL;DR Quote a wrapper that checks response.ok From the fetch() docs: Quote A fetch() promise only rejects when a network error is encountered (which is usually when there’s a permissions issue or similar). A fetch() promise does not reject on HTTP errors (404, etc.). Instead, a then() handler must check the Response.ok and/or Response.status properties. To the solutions Handling Failed HTTP Responses With fetch() How to handle HTTP code 4xx responses in fetch api 3 1 Link to comment Share on other sites More sharing options...
elabx Posted November 12, 2020 Share Posted November 12, 2020 Seems UIKit is returning a Promise? I think this should work?? Got it from here: util.ajax('/data/newsletter/', { responseType: 'json', method: 'POST', data: JSON.stringify({ mail:mail, sms:sms, msg:msg, cmt:cmt, }), }) .then(function(xhr) { console.log(xhr); if(xhr.status !== 200) { UIkit.modal.alert('error xyz'); } }, function(error){ //error goes here }); Link to comment Share on other sites More sharing options...
bernhard Posted November 12, 2020 Author Share Posted November 12, 2020 Thx @kongondo that helped a lot ? Also thx @elabx this is what seems to work for me: util.ajax('/data/newsletter/', { responseType: 'json', method: 'POST', data: JSON.stringify({ mail:mail, sms:sms, msg:msg, cmt:cmt, }), }) .then(function(response) { // show success message }).catch(function(error) { UIkit.modal.alert('Es ist leider ein Fehler aufgetreten!<pre style="margin-top:5px;">'+error+'</pre>'); util.removeClass(button, 'loading'); }); No idea how exactly I was using the catch statement before, but it somehow did not fire. Now everything seems to be fine, but I'll have to do more testing ? 1 hour ago, kongondo said: You will need to unlearn jQuery ?. Probably not the best idea for a PW developer ? 2 Link to comment Share on other sites More sharing options...
adrian Posted November 12, 2020 Share Posted November 12, 2020 @bernhard - this might also be useful for getting PW's $config->ajax to work and also make Tracy capture the errors. Not sure how to do it within uikit requests. It's automatic with jquery. 2 Link to comment Share on other sites More sharing options...
kongondo Posted November 13, 2020 Share Posted November 13, 2020 14 hours ago, bernhard said: Probably not the best idea for a PW developer Touché! ?. In my own modules though, I am eliminating jQuery. Wherever possible I use vanilla JavaScript. Link to comment Share on other sites More sharing options...
bernhard Posted November 13, 2020 Author Share Posted November 13, 2020 57 minutes ago, kongondo said: Touché! ?. Yes and no. This post is a result of removing jQuery from my project, so you are on one hand spot on. I'M using uikit for the frontend and I didn't want to include another framework when uikit already ships with lots of nice little helpers. Only things that I've added so far are custom methods for slideDown(), slideToggle() and slideUp() (https://gist.github.com/skttl/b8ea597ebf2db66a3e2a06491f7b4029) Thx @adrian, you are always one step ahead ? This is my final (?) version: let mail = util.$('#frm-mail').value; let sms = util.$('#frm-sms').value; let msg = util.$('#nl-form input[name=message]').value; let cmt = util.$('#nl-form input[name=comment]').value; let csrf = util.$('#tm-newsletter input[name=csrf]'); // show loading icon util.addClass(button, 'loading'); // setup headers let headers = {} headers['X-Requested-With'] = 'XMLHttpRequest'; headers['X-'+util.data(csrf, 'tokenname')] = util.data(csrf, 'tokenvalue'); // send ajax util.ajax('/data/newsletter/', { responseType: 'json', method: 'POST', headers, data: JSON.stringify({ mail:mail, sms:sms, honey:msg+cmt, }), }) .then(function() { // success RockUikit.slideUp(button.closest('form')); RockUikit.slideDown(util.$('#tm-newsletter .tm-success')); }).catch(function(error) { UIkit.modal.alert('Es ist leider ein Fehler aufgetreten!<pre style="margin-top:5px;">'+error+'</pre>'); util.removeClass(button, 'loading'); }); Server side: // template if(!$config->ajax) throw new Wire404Exception(); $gg->subscribe(); // module public function subscribe() { try { $input = json_decode(file_get_contents('php://input')); if(!$input) throw new WireException("No data"); if(!$this->wire->session->CSRF->hasValidToken()) { throw new WireException("CSRF failed"); } $mail = $this->wire->sanitizer->text($input->mail); $sms = $this->wire->sanitizer->text($input->sms); $honey = $this->wire->sanitizer->text($input->honey); // honeypot if($honey) throw new WireException("Invalid request"); // both empty? if(!$mail AND !$sms) throw new WireException("No data"); // create page $p = new Page(); $p->template = 'signup'; $p->parent = '/data/newsletter'; $p->title = implode(" | ", [ date("Y-m-d H:i:s"), $mail, $sms ]); $p->json = json_encode(['mail'=>$mail, 'sms'=>$sms]); $p->save(); die('success'); } catch(\Throwable $th) { http_response_code(400); die($th->getMessage()); } } Thx guys! Any ideas for improvement? ? 2 Link to comment Share on other sites More sharing options...
Recommended Posts