Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load a new external HTML for each event?

  • 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/[email protected]/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/[email protected]/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.

like image 805
Peter Krauss Avatar asked Mar 16 '18 19:03

Peter Krauss


2 Answers

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

like image 57
Traxo Avatar answered Sep 27 '22 20:09

Traxo


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

like image 28
2 revs Avatar answered Sep 27 '22 19:09

2 revs