When i use materialize tabs for my design in vue js 1. It's not working on the first time when i load the page. After reloading the page it's working perfectly. I've used the $('ul.tabs').tabs(); function in ready funtion. Below is the screen-shot of the page when it loads for the first time.
tabs not working in vue.js 1
`<ul class="tabs tabs-fixed-width white z-depth-2">
<li class="tab left-tab">View Testimonials</li>
<li class="tab right-tab"><a class="black-text bolder font-1-5x" href="#create_testimonial">Create Testimonial</a></li>
<li class="indicator brand-color"></li>
</ul>`
--- This is my html
`
import Sidebar from '../Sidepanel.vue';
Vue.directive('chosen', {
twoWay: true, // note the two-way binding
bind: function () {
$(this.el)
.chosen({
width: '100%'
})
.change(function (ev) {
var i, len, option, ref;
var values = [];
ref = this.el.selectedOptions;
for (i = 0, len = ref.length; i < len; i++) {
option = ref[i];
values.push(option.value)
}
this.set(values);
}.bind(this));
},
update: function (nv, ov) {
// note that we have to notify chosen about update
$(this.el).trigger("chosen:updated");
}
});
export default {
components: {
'header-component': Sidebar
},
data: function () {
return {
loader: '<div class="loading full-width full-height fixed top-off left-off row"><div class="progress cyan auto top-25x col s12 m3 float"><div class="indeterminate"></div></div><h5 class="black-text top-25x center-align relative black-text">Processing..</h5></div>',
response: {
edit : false,
_token: $('meta[name=csrf_token]').attr('content'),
passage_details:{
}
}
}
},
ready: function () {
let vm = this;
window.document.title = "Testimonials";
$('ul.tabs').tabs();
$(".chosen-select").chosen({width: '100%'});
},
computed:{
},
methods: {
}
}
`
---- This is my script
Related
I have this problem, that lightgallery can be opened only once. Each next click on button is unresponsive. I'm using lightgallery as component.
In my parent component I have two buttons, for opening image or video gallery
ParentComponent.vue
<template>
<div>
<button class="btn-secondary" #click="showGallery('IMAGE')">
{{ $t('showImages') }}
</button>
<button class="btn-secondary" #click="showGallery('VIDEO')">
{{ $t('playVideo') }}
</button>
<LightGallery
v-if="galleryVisible" :gallery-items="galleryItems"
:gallery-type="galleryType" :user-subscription="userSubscription">
</LightGallery>
</div>
<template>
<script>
import LightGallery from "./subComponents/LightGallery.vue";
export default {
name: "Location",
components: {
LightGallery: LightGallery,
},
data() {
return {
// image / video slide show data
locationImages: [],
locationVideo: [],
galleryItems: {},
galleryVisible: false,
galleryType: 'IMAGE',
};
},
methods: {
showGallery(type) {
this.galleryItems = {};
this.galleryVisible = true;
this.galleryType = type;
if (type === 'IMAGE') {
this.galleryItems = this.locationImages;
} else if (type === 'VIDEO') {
this.galleryItems = this.locationVideo
}
},
hideGallery() {
this.galleryItems = {};
this.galleryVisible = false;
},
};
</script>
And this is my child (lightgallery) component
<template>
<div id="lightgallery">
</div>
</template>
<script>
// Light gallery
import 'lightgallery.js'
import 'lightgallery.js/dist/css/lightgallery.css'
import 'lg-zoom.js'
import 'lg-autoplay.js'
import 'lg-fullscreen.js'
import 'lg-hash.js'
import 'lg-pager.js'
import 'lg-share.js'
import 'lg-thumbnail.js'
import 'lg-video.js'
// Light gallery
export default {
name: "LightGallery",
props: {
galleryItems: {
type: Array,
required: true
},
galleryType: {
type: String,
required: true
},
userSubscription: {
type: Object,
required: false,
default: {
active: false
}
}
},
methods: {
openGallery() {
// prepare images / video to display them in lightGallery
let dynamicElements = [];
if (this.galleryType === 'IMAGE') {
this.galleryItems.forEach(function (value) {
dynamicElements.push({
src: '/' + value.hd_path,
thumb: '/' + value.thumb_path,
});
});
}
if (this.galleryType === 'VIDEO') {
this.galleryItems.forEach(function (value) {
dynamicElements.push({
src: 'https://vimeo.com/' + value.vimeo_id,
});
});
}
let lg = document.getElementById('lightgallery');
window.lightGallery(lg, {
mode: 'lg-slide',
download: false,
thumbnail: true,
dynamic: true,
dynamicEl: dynamicElements,
autoplayFirstVideo: true,
loadVimeoThumbnail: false,
});
lg.addEventListener('onCloseAfter', function (event, index, fromTouch, fromThumb) {
lg.data('lightGallery').destroy(true);
}, false);
window.lightGallery(lg);
},
},
mounted() {
this.openGallery();
}
};
</script>
The problem!
On first "refresh" page reload if I click on button Show image or show video, gallery opens and it works well. When I close gallery I see error in developer tools (maybe complletly unrelated, with my problem)
Each next click on buttons Show image or show video does nothing. So how can I properly destroy Lightgallery so I will be able to reopen it? If you need any additional informations, please let me know and I will provide. Thank you!
Try adding this line to your showGallery method.
showGallery(type) {
this.galleryVisible = false // <<--- this line
this.galleryItems = {};
this.galleryVisible = true;
this.galleryType = type;
if (type === 'IMAGE') {
this.galleryItems = this.locationImages;
} else if (type === 'VIDEO') {
this.galleryItems = this.locationVideo
}
},
Light Gallery only seems to work once. But the above line of code will re-create the Light Gallery Component and you'll have a fresh instance of Light Gallery component (exactly what you have on a page load) each time you click on one of the buttons that would initiate the Light Gallery.
<template>
...
<div class="pagination">
<el-pagination
#current-change="handleCurrentChange"
layout="prev, pager, next"
:total="totalCount">
</el-pagination>
</div>
</template>
<script>
import Vue from 'vue';
Vue.use(ElementUI);
export default {
data() {
return {
tableData: [],
orderTableUrl: setting.orderTableUrl,
width: 110,
page_size: 10,
page_num: 1,
messages: [],
totalCount: 100,
}
},
created() {
this.getTableData()
},
methods: {
getTableData: function () {
let self = this;
axios.Get({
url: self.orderTableUrl,
params: {
'page_size': self.page_size,
'page_num': self.page_num
},
callback: function (res) {
self.tableData = res.data.orders;
self.totalCount = res.data.orders_total_pages;
console.log(self.totalCount)
}
});
},
}
}
the pagination part use element.ui .
Here is my problem: in method callback, console.log can echo real num of total page, but it cannot display on template, and only can see the num 1 of page on window.
I'm so puzzled for that.
Is it said that vue can immediately show data on change on view
finish the question. the ':total' does work, just surprised that it means the count of objects instead of pages ...
I want to make a feed that automatically loads items when the bottom of the current page is reached, however the iron-scroll-threshold doesn't trigger. I'm using my api call to fill the items in the template and the restaurants load just fine. Also when I bind a load function to a button it works just fine. It seems that the iron-scroll-threshold never triggers. Can anyone explain to me what I'm missing/doing wrong?
Code:
<iron-scroll-threshold id="threshold" lower-threshold="100" on-lower-threshold="loadMoreData">
<div id="scroller" class="vertical layout center" fill>
<template is="dom-repeat" items="[[restaurants]]" filter="{{computeFilter(searchInput)}}" scroll-target="threshold" on-scroll="_scrollHandler">
<!-- Items -->
</template>
<div class="loadingIndicator" hidden$="[[!loadingRestaurants]]">
<paper-spinner active$="[[loadingRestaurants]]"></paper-spinner> Fetching restaurants</b>
</div>
</div>
</iron-scroll-threshold>
<script>
Polymer({
is: 'my-view2',
properties: {
restaurants:{
type: Array,
value: []
},
offset:{
type: Number,
value: 0
},
limit:{
type: Number,
value: 50
},
loadingRestaurants: Boolean
},
ready: function () {
this.$.requestRestaurants.generateRequest();
},
handleResponse: function (data) {
var self = this;
var response = data.detail.response;
response.forEach(function(restaurant){
self.push('restaurants', restaurant);
});
console.log(this.restaurants);
this.$.threshold.clearTriggers();
},
toggle: function(e) {
console.log(this.$.threshold.top);
var index = "#collapse" + e.model.__data.index;
this.$$(index).toggle();
this.loadMore();
},
loadMore: function() {
console.log("test");
this.offset+=50;
this.limit+=50;
this.$.requestRestaurants.generateRequest();
this.$.threshold.clearLower();
this.$.threshold.clearTriggers();
}
});
The naming was inconsistent
on-lower-threshold="loadMoreData"
loadMore: function()
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.
How to create a Vue.js logic to handle all tag elements with the same class selector?
I have this simple code: http://jsfiddle.net/x2spo1qu/
var dropdown = new Vue({
el: '.dropdown',
data: {
is_open : false
},
methods: {
onClick: function (event) {
// # toggle the dropdown open/closed state
// ---
this.is_open = ! this.is_open;
},
mouseLeave: function (event) {
// # set show of dropdown to false
// ----
this.is_open = false;
}
}
});
But it only works for the first dropdown in the HTML and does not work for the second.
Please explain me how to do this.
From vuejs.org :
Vue.js uses DOM-based templating. Each Vue instance is associated with a corresponding DOM element. When a Vue instance is created, it recursively walks all child nodes of its root element while setting up the necessary data bindings. After the View is compiled, it becomes reactive to data changes.
you can achieve this using Vue component system
follow this example :
var bs3_dropdown = Vue.extend
({
props: ['name'],
replace: true,
template: '<li class="dropdown" v-class="open : is_open" v-on="mouseleave : mouseLeave"> {{ name }} <span class="caret"></span> <ul class="dropdown-menu" role="menu"> <content></content> </ul> </li>',
data: function () {
return {
is_open: false,
}
},
methods : {
onClick : function(event) {
// # toggle the dropdown open/closed state
// ---
this.is_open = ! this.is_open;
},
mouseLeave : function(event) {
// # set show of dropdown to false
// ----
this.is_open = false;
}
},
created: function () {
console.log('An instance of MyComponent has been created!')
}
});
Vue.component('bs3-dropdown', bs3_dropdown);
full : http://jsfiddle.net/msa965j5/
there is some bug beacuse of initial HTML