Resource file helper/json.json
{
"content": {
"content_body": "<a href='#' v-on:click.prevent='getLink'>{{ button }}</a>",
"content_nav": "",
}
}
Vue main.js file
new Vue({
el: 'body',
data: {
text: 'Lorem sss',
},
methods: {
getLink: function(){
this.$http.get('http://localhost/vuejs/helper/json.json').then((resp) => {
this.$set('text', resp.data.content.content_body);
}, (resp) => {
console.log('error');
})
}
}
})
Output: Not Renderer
{{ button }}
Event does not work when the button is clicked. Data can not be loaded.
Vue.resourse have no relation to this problem
becouse html string from json isn't compiled.
Here a little test based on your example:
<body>
<div v-el:sample></div>
</body>
var test = new Vue({
el: 'body',
data: {
button: 'Lorem sss',
},
methods: {
getLink: function(){
var r = Math.floor(Math.random() * (4 - 1)) + 1;
this.$set('button', ['','btn1','btn2','btn3'][r] );
},
getCompiled: function() {
$(this.$els.sample).empty()
var element = $(this.$els.sample).append("<a href='#' v-on:click.prevent='getLink'>{{ button }}</a>");
this.$compile(element.get(0));
$(this.$els.sample).prepend('<p>Compiled button:</p>')
}
},
ready: function() {
this.getCompiled();
}
})
jsfidle
Related
I am having difficulty to integrate paypal into my web page using vue. I am getting any paypal button. If I use the same code in the vue cli then it's working but when I am using this code in index.html using vue cdn then it's not working. I need it to work in index.html without using the cli. Can anyone help me please?
HTML code
<div id="app">
<payment-method></payment-method>
</div>
Vue js Code
<script>
// Define a new component called button-counter
Vue.component('payment-method', {
template: '<div>'+
'<div v-if="!paidFor">'+
'<h1>Buy this Lamp - ${{ product.price }} OBO</h1>'+
'<p>{{ product.description }}</p>'+
'</div>'+
'<div v-if="paidFor">'+
'<h1>Noice, you bought a beautiful lamp!</h1>'+
'</div>'+
'<div ref="paypal"></div>'+
'</div>',
data: function() {
return {
loaded: false,
paidFor: false,
product: {
price: 777.77,
description: "leg lamp from that one movie",
img: "./assets/lamp.jpg"
}
};
},
mounted: function() {
const script = document.createElement("script");
script.src ="https://www.paypal.com/sdk/js?client-id=client-id=YOUR-CLIENT-ID";
script.addEventListener("load", this.setLoaded);
document.body.appendChild(script);
},
methods: {
setLoaded: function() {
this.loaded = true;
window.paypal
.Buttons({
createOrder: (data, actions) => {
return actions.order.create({
purchase_units: [
{
description: this.product.description,
amount: {
currency_code: "USD",
value: this.product.price
}
}
]
});
},
onApprove: async (data, actions) => {
const order = await actions.order.capture();
this.paidFor = true;
console.log(order);
},
onError: err => {
console.log(err);
}
}).render(this.$refs.paypal);
}
}
})
var vue = new Vue({
el: '#app',
data: {
}
})
</script>
I need insert script like this
<div data-player-id="912d05c">
<script src="//cdn.flowplayer.com/players/7/flowplayer.async.js">
{
"src": "https://s3.amazonaws.com/69693f173770c49cbb5.mp4"
}
</script>
</div>
to inside of html under the vue.
So I found that I need to generate script tag by js but I'm not sure how to add
{
"src": "https://s3.amazonaws.com/69693f173770c49cbb5.mp4"
}
to this script tag
Code what I have (simplified):
<div id="app">
<div id="videocontent"></div>
</div>
el: "#app",
data: {},
created: function() {
let playerContainer = document.createElement('div');
playerContainer.setAttribute('data-player-id','912d05c');
let flowplayerScript = document.createElement('script');
flowplayerScript.setAttribute('src', '//cdn.flowplayer.com/players/7/flowplayer.async.js');
flowplayerScript.innerText = {"src": "https://s3.amazonaws.com/productionadgate_video/eceae5886caaf69693f173770c49cbb5.mp4"};
playerContainer.append(flowplayerScript);
let container = document.getElementById('videocontent');
container.append(playerContainer);
}
and flowplayerScript.innerText = {"src": "https://s3.amazonaws.com/productionadgate_video/eceae5886caaf69693f173770c49cbb5.mp4"}; is not correclty injected and player is always loading but not showing videos. Also I was tried tu use:
flowplayerScript.onload = function(){
return {
"src": "https://s3.amazonaws.com/productionadgate_video/eceae5886caaf69693f173770c49cbb5.mp4"
}
};
but still not working :( and I'm getting the error like:
SyntaxError: Unexpected token $ in JSON at position 0 flowplayer.async.js:2
You can use pure JavaScript installation, then init flowplayer in 'mounted' method.
new Vue({
el: "#app",
mounted: function() {
this.$nextTick(function() {
// select the above element as player container
let containerEl = document.getElementById("videocontent")
// install flowplayer into selected container
flowplayer(containerEl, {
clip: {
sources: [
{ type: "application/x-mpegurl",
src: "//mydomain.com/video.m3u8" },
{ type: "video/mp4",
src: "//mydomain.com/video.mp4" }
]
}
})
})
}
})
jsfiddle
I am trying to create a DownloadButton component in VueJS that animates when clicked, and stops animating upon completion of the download. The DownloadButton component will be used in a table where its repeated many times. I want the download method to be contained in the parent. The problem is that changing the loading variable causes all the components to be affected rather than just the one being clicked.
Parent:
<DownloadButton #click.native="download" :loading="loading"></DownloadButton>
<DownloadButton #click.native="download" :loading="loading"></DownloadButton>
<DownloadButton #click.native="download" :loading="loading"></DownloadButton>
methods: {
download() {
this.loading = true
// wait for the download procedure to finish...
this.loading = false
}
}
You should monitor loading state of each button not just global loading.
Here is quick and simple example of what you want I think:
Vue.component("download-button", {
template: "#dbTemplate",
props: ['loading'],
computed: {
stateText() {
return this.loading ? 'Loading...' : 'Load';
}
}
});
new Vue({
el: "#app",
data: {
resources: [
{ date: new Date(), url: "some-url1" },
{ date: new Date(), url: "some-url2" },
{ date: new Date(), url: "some-url3" },
{ date: new Date(), url: "some-url4" }
],
resourceStates: {}
},
methods: {
downloadResource(resource) {
this.$set(this.resourceStates, resource.url, true);
new Promise((resolve, reject) => {
setTimeout(() => resolve(new Date()), 1000);
}).then((date) => {
resource.date = date;
this.$set(this.resourceStates, resource.url, false);
})
},
isLoading(resource) {
return !!this.resourceStates[resource.url];
}
}
});
<script src="https://unpkg.com/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<div v-for="res in resources" :key="res.url" style="padding: 10px 0">
{{ res.date.toLocaleString() }}
<download-button #click.native="downloadResource(res)" :loading="isLoading(res)">
</download-button>
</div>
</div>
<script type="text/template-x" id="dbTemplate">
<button :disabled="loading">
{{ stateText }}
</button>
</script>
Im grabbing this JSON object and passing it on to this Vue. However, It is not updating on my page, but the object is there since window.alert(jobj.Name) works fine. Here is my vue and my view.
var app2 = new Vue({
el: '#menuPage',
data: {
HeaderTitle: 'NOT CHANGED',
content_body: 'test body',
},
methods: {
loadMENU: function (jobj) {
app2 = this;
window.location.href = "tools/menu.html"; //relative to domain
window.alert(jobj.Name);
this.HeaderTitle = jobj.Name;
}
} });
<div id="menuPage">{{HeaderTitle}}</div>
It is only showing "NOT CHANGED" Instead of the object Name.
You didn't call the method. You should use a button to trigger the method.
html
<div id="menuPage">{{HeaderTitle}}
<button v-on:click="loadMENU">button</button>
</div>
javascript
var app2 = new Vue({
el: '#menuPage',
data: {
HeaderTitle: 'NOT CHANGED',
content_body: 'test body',
},
methods: {
loadMENU: function () {
app2 = this;
const herf = window.location.href;
window.alert(herf);
this.HeaderTitle = herf;
}
} });
I have a very specific need that cannot realy be solved with standard data-binding.
I've got a leaflet map that I want to bind with a vue view-model.
I succeeded to display geojson features kinda bounds to my view, but I'm struggling at displaying a popup bound with vue.js
The main question is : "How to open a popup (possibly multiple popups at the same time) and bind it to a view property "
For now I've come to a working solution, but this is aweful :
map.html
<div id="view-wrapper">
<div id="map-container"></div>
<div v-for="statement in statements" id="map-statement-popup-template-${statement.id}" style="display: none">
<map-statement-popup v-bind:statement="statement"></map-statement-popup>
</div>
</div>
<!-- base template for statement map popup -->
<script type="text/template" id="map-statement-popup-template">
{{ statement.name }}
</script>
map.js
$(document).ready(function() {
var map = new L.Map('map-container');
map.setView(new L.LatLng(GLOBALS.MAP.STARTCOORDINATES.lng, GLOBALS.MAP.STARTCOORDINATES.lat), GLOBALS.MAP.STARTZOOM);
var osm = new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
osm.addTo(map);
//Initialize map dynamic layers
var mapLayers = {};
//View-model data-bindings
var vm = new Vue({
el: '#view-wrapper',
data: {
statements: []
},
methods: {
getStatements: function() {
return $.get('api/statements');
},
updateStatements: function() {
var that = this;
return that.getStatements().then(
function(res) {
that.statements = res.data;
}
);
},
refreshStatements: function() {
mapLayers.statements.layer.clearLayers();
if(this.statements && this.statements.length){
var geoJsonStatements = geoJsonFromStatements(this.statements);
mapLayers.statements.layer.addData(geoJsonStatements);
}
},
handleStatementFeature: function(feature, layer) {
var popupTemplateEl = $('#map-statement-popup-template-' + feature.properties.statement.id);
layer.bindPopup(popupTemplateEl.html());
var statementIndex = _.findIndex(this.statements, {statement:{id: feature.properties.statement.id}});
if(feature.geometry.type === 'LineString') {
this.statements[statementIndex].layer = {
id: L.stamp(layer)
};
}
},
openStatementPopup: function(statement) {
if(statement.layer) {
var featureLayer = mapLayers.statements.layer.getLayer(statement.layer.id);
featureLayer.openPopup();
}
}
},
created: function() {
var that = this;
//Set dynamic map layers
var statementsLayer = L.geoJson(null, {
onEachFeature: this.handleStatementFeature
});
mapLayers.statements = {
layer: statementsLayer
};
map.addLayer(mapLayers.statements.layer);
this.updateStatements().then(this.refreshStatements);
this.$watch('statements', this.refreshStatements);
},
components: {
'map-statement-popup': {
template: '#map-statement-popup-template',
props: {
statement: null
}
}
}
});
function geoJsonFromStatementsLocations(statements){
var geoJson = {
type: "FeatureCollection",
features: _.map(statements, function(statement) {
return {
type: "Feature",
geometry: {
type: "LineString",
coordinates: statement.coordinates
},
properties: {
statement: statement
}
};
});
};
return geoJson;
}
});
This seems pretty aweful to me, because I have to loop over statements with a v-for, render a div for my custom element for every statement, hide it, then use it in the popup, grabbing it with a dynamic id technique.
I would like to do something like this :
map.html
<div id="view-wrapper">
<div id="map-container"></div>
</div>
<!-- base template for statement map popup -->
<script type="text/template" id="map-statement-popup-template">
{{ statement.name }}
</script>
map.js
$(document).ready(function() {
[...]
//View-model data-bindings
var vm = new Vue({
el: '#view-wrapper',
data: {
statements: []
},
methods: {
handleStatementFeature: function(feature, layer) {
var popupTemplateEl = $('<map-statement-popup />');
var scope = { statement: feature.properties.statement };
var compiledElement = this.COMPILE?(popupTemplateEl[0], scope);
layer.bindPopup(compiledElement);
}
},
components: {
'map-statement-popup': {
template: '#map-statement-popup-template',
props: {
statement: null
}
}
}
});
function geoJsonFromStatementsLocations(statements){
var geoJson = {
type: "FeatureCollection",
features: _.map(statements, function(statement) {
return {
type: "Feature",
geometry: {
type: "LineString",
coordinates: statement.coordinates
},
properties: {
statement: statement
}
};
});
};
return geoJson;
}
});
... but I couldn't find a function to "COMPILE?" based on a defined scope. Basically I want to :
Create a custom element instance
Pass it a scope
Compile it
EDIT : Actually, I could find $compile function. But it's often used to compile appended child to html. I don't want to append it THEN compile it. I'd like to compile it then let leaflet append it for me.
Would this work for you? Instead of using a component, you create a new element to be passed to bindPopup, and you new Vue on that element, with your data set appropriately.
new Vue({
el: 'body',
data: {
popups: [1, 2, 3],
message: "I'm Dad",
statements: []
},
methods: {
handleFeature: function(id) {
const newDiv = document.createElement('div');
const theStatement = {
name: 'Some name for ' + id
};
newDiv.innerHTML = document.getElementById('map-statement-popup-template').innerHTML;
new Vue({
el: newDiv,
data: {
statement: theStatement
},
parent: this
});
// Mock call to layer.bindPopup
const layerEl = document.getElementById(id);
this.bindPopup(layerEl, newDiv);
},
bindPopup: function(layerEl, el) {
layerEl.appendChild(el);
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<div class="leaflet-zone">
<div v-for="popup in [1,2,3]">
<button #click="handleFeature('p-' + popup)">Bind</button>
<div id="p-{{popup}}"></div>
</div>
</div>
<template id="map-statement-popup-template">
{{ statement.name }} {{$parent.message}}
</template>
I think you could do the same thing with $compile, but $compile is poorly (really un-) documented and intended for internal use. It is useful for bringing a new DOM element under control of the current Vue in the current scope, but you had a new scope as well as a new DOM element, and as you noted, that binding is exactly what Vue is intended to do.
You can establish a parent chain by specifying the parent option as I have updated my snippet to do.