7
  • Problem: I want to show an v-html into the modal interface, and the content comes from an URL (ajax)... The snipped code is running, but it is bad, not professional: try to run. You click GO, take a message saying to CLOSE and click GO again...
    I need to "promisify my code" with Vue's best practices.

Question: how to do this interface better, all with Vuetify?

I need one-click (GO) interface, and with mininal waiting time for user.

(need also to load other URLs, so using AJAX many times as other buttons, etc.)

I am supposing that Vuetify have good approaches to AJAX-load (as these), so I need to use the best one! for this situation.

PS: I not see how to implement the Vue-AJAX strategies in a single HTML page (not a big Node.js system).

A simplified ugly-interface example

It is running, but is mixing non-VueJS code and have all the explained problems, to be fixed by the answer.

var URL = 'https://codepen.io/chriscoyier/pen/difoC.html';    
var loadFromUrl_cache = '... PLEASE WAYTE 10 seconds ...'+
    '<br/>close and back here.';

function loadFromUrl(URL,tmpStore) {
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == XMLHttpRequest.DONE) {
           if (xmlhttp.status == 200) {
               loadFromUrl_cache = xmlhttp.responseText;
           } else {
               alert('ERROR, something else other than status 200:'+
               xmlhttp.status);
           }
        }
    };
    xmlhttp.open("GET", URL, true); // async
    xmlhttp.send();
}

// to get rid of "missing v-app" error message
var app = document.createElement('div');
app.setAttribute('data-app', true);
document.body.appendChild(app);

let mainVue = new Vue({ el: '#main' });

new Vue({
  el: '#appDlg',
  data() {
    return {
      dialog: false,
      ct_header: 'the header1 here',
      ct_body: 'the body1 here'
    }
  },
  mounted() {
    mainVue.$on('go-modal', this.handleMain);
  },
  methods: {
    handleMain(data) {
      this.ct_header = data.title;
      loadFromUrl(URL,'tmp-store');
      this.ct_body = loadFromUrl_cache;
      this.dialog = true;
    }
  }
});
.myDialog { 
  padding: 10px;
  height: 100%;
  background-color: white; 
}

.myDialog .btn { margin: 20px 0 0 -4px; }
<link href="https://unpkg.com/vuetify@0.14.8/dist/vuetify.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<script src="https://unpkg.com/vuetify@0.14.8/dist/vuetify.min.js"></script>
<link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet" type="text/css">

<div id="main">
  <v-expansion-panel>
    <v-btn @click="$emit('go-modal', {title: 'Hello', body: 'Bye!'})">Go</v-btn>
  </v-expansion-panel>
</div>

<div id="appDlg">
  <v-dialog v-model="dialog" fullscreen>
    <div class="myDialog">
      <v-btn @click="dialog = false">Close</v-btn>
      <h4>{{ ct_header }}</h4>
      <div v-html="ct_body"></div>
      <v-btn @click="dialog = false">Close</v-btn>
    </div>
  </v-dialog>
</div>
   

PS: thanks to the code at this answer. If you prefer you can use codepen/NYRGyv.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Peter Krauss
  • 13,174
  • 24
  • 167
  • 304
  • what do you mean by "ugly"? You don't have any css afaics. – Traxo Mar 19 '18 at 08:02
  • Hi @Traxo, sorry, I edited, it is "not professional" ;-) need more friendly and elegant interface. Not 3 clicks (GO/CLOSE/GO), only one click (GO). And need all as Vue code, my `loadFromUrl()` is not Vue.js – Peter Krauss Mar 19 '18 at 11:08

2 Answers2

4

I am supposing that Vuetify have good approaches to AJAX-load (as these), so I need to use the best one! for this situation.

You can try axios

then you can change for example ct_body html like so:

handleMain(data) {
    var URL = "your HTML url here";
    axios.get(URL)
    .then(response => {
        this.ct_body = response.data;
    })
}

Currently your problem is that you are trying to change html before you even fetch the data.

You should set it after you retrieve it with ajax call.

Note that fetching HTML from url is not instant (tho it should be relatively fast), so depends on your case where you want to put loading indicator. Thus it's up to you where you want to set this.dialog = true - inside .then() will make it open only when you retrieve html data.

Codepen

Traxo
  • 18,464
  • 4
  • 75
  • 87
  • Hi, **axios** is perfect! Please show the solution running in a fork of https://codepen.io/ppKrauss/pen/NYRGyv PS: the URL is a global there, you need only to delete my `handleMain()`, my `loadFromUrl()` and add your 7 lines... And load the axios script. – Peter Krauss Mar 19 '18 at 12:02
  • @PeterKrauss edited. note that I include it with `script`, but only because its on codepen. read docs on how to install it. – Traxo Mar 19 '18 at 12:07
1

Pure Javascript (ECMAScript 2015)

We can use fetch() and its embedded promises! See developer.mozilla.org/Fetch_API/Using_Fetch.

handleMain(data) {
  var self = this;
  self.ct_header = data.title;      
  fetch(URL)
  .then(function(res) { return res.text(); })
  .then(function(data) {
    self.ct_body = data;
    self.dialog = true;
  });
}

... Is equivalent to Axios, but, as it seems exactly the same, the solution is better because avoid to lost of CPU-time, internet-bandwidth and memory (13kb) loading Axios. See

https://codepen.io/ppKrauss/pen/oqYOrY

Peter Krauss
  • 13,174
  • 24
  • 167
  • 304
  • >"it seems exactly the same", not same, check compatibility for example: https://caniuse.com/#feat=fetch So it depends on your needs of course (it's possible that `fetch` is sufficient in your case). – Traxo Mar 20 '18 at 13:23
  • Hi @Traxo, yes, the eternal problem with MS-IE... And, of course, when adopting *fetch()*, the older browsers (before 2015) are also excluded. But I, my customers and my community, we are modern and we hate Microsoft, so we can ignore MS-IE :-) – Peter Krauss Mar 20 '18 at 19:21