link1370 link1371 link1372 link1373 link1374 link1375 link1376 link1377 link1378 link1379 link1380 link1381 link1382 link1383 link1384 link1385 link1386 link1387 link1388 link1389 link1390 link1391 link1392 link1393 link1394 link1395 link1396 link1397 link1398 link1399 link1400 link1401 link1402 link1403 link1404 link1405 link1406 link1407 link1408 link1409 link1410 link1411 link1412 link1413 link1414 link1415 link1416 link1417 link1418 link1419 link1420 link1421 link1422 link1423 link1424 link1425 link1426 link1427 link1428 link1429 link1430 link1431 link1432 link1433 link1434 link1435 link1436 link1437 link1438 link1439 link1440 link1441 link1442 link1443 link1444 link1445 link1446 link1447 link1448 link1449 link1450 link1451 link1452 link1453 link1454 link1455 link1456 link1457 link1458 link1459 link1460 link1461 link1462 link1463 link1464 link1465 link1466 link1467 link1468 link1469 link1470 link1471 link1472 link1473 link1474 link1475 link1476 link1477 link1478 link1479 link1480 link1481 link1482 link1483 link1484 link1485 link1486 link1487 link1488 link1489 link1490 link1491 link1492 link1493 link1494 link1495 link1496 link1497 link1498 link1499 link1500 link1501 link1502 link1503 link1504 link1505 link1506

[Vue.js] Restrict full screen element render from external SDK

I’m using an SDK that render a full screen element on the page (100% width and height). to restrict this.
Im using Vue.js in this project.

I tried to render inside a iframe following this demo:

Vue.component(‘i-frame’, {

render(h) {
return h(‘iframe’, {
on: { load: this.renderChildren }
})
},
beforeUpdate() {
//freezing to prevent unnessessary Reactifiation of vNodes
this.iApp.children = Object.freeze(this.$slots.default)
},
methods: {
renderChildren() {
const children = this.$slots.default
const body = this.$el.contentDocument.body
const el = document.createElement(‘DIV’) // we will mount or nested app to this element
body.appendChild(el)

const iApp = new Vue({
name: ‘iApp’,
//freezing to prevent unnessessary Reactifiation of vNodes
data: { children: Object.freeze(children) },
render(h) {
return h(‘div’, this.children)
},
})

iApp.$mount(el) // mount into iframe

this.iApp = iApp // cache instance for later updates

}
}
})

Vue.component(‘test-child’, {
template: `<div>
<h3>{ title }</h3>
<p>
<slot/>
</p>
</div>`,
props: [‘title’],
methods: {
log: _.debounce(function () {
console.log(‘resize!’)
}, 200)
},
mounted() {
this.$nextTick(() => {
const doc = this.$el.ownerDocument
const win = doc.defaultView
win.addEventListener(‘resize’, this.log)
})
},
beforeDestroy() {
const doc = this.$el.ownerDocument
const win = doc.defaultView
win.removeEventListener(‘resize’, this.log)
}
})

new Vue({
el: ‘#app’,
data: {
dynamicPart: ‘InputContent’,
show: false,
}
})

https://jsfiddle.net/Linusborg/ohznser9/

And read this question:
Render Component in iframe using vuejs without src attribute

But nothing restrict this behavior.
The SDK in question are the Zoom Web SDK

Solution :

I think you should give it a shot using A Modal to control views and what to show. I use it for a current project to display different view there is full control over how much of the screen it should take
Try this plugin Vue-js-modal. It is very nice and well documented

[Vue.js] Vue + TypeScript - Recommended folder structure convention for placing custom typings?

Is there a recommended convention in where to place the custom type definition files in a vue.js project?

I’ve been using a folder named ./src/types with this kind of tsconfig:

{
“compilerOptions”: {

“typeRoots”: [
“node_modules/@types”,
“types”
]
}
}

Somebody told me that vue.js or Webpack would pick up files in ./@types/ folder automatically without needing to add this to ./tsconfig.json - however, I did not find a reference to such information?

Solution :

According to TypeScript website, TypeScript automatically loads types in folders if you have referenced them in the code.

@types, typeRoots and types

By default all visible @types packages are included in your
compilation. Packages in node_modules/@types of any enclosing folder
are considered visible; specifically, that means packages within
./node_modules/@types/, ../node_modules/@types/,
../../node_modules/@types/, and so on.

If typeRoots is specified, only packages under typeRoots will be
included. For example:

{
“compilerOptions”: {
“typeRoots” : [“./typings”]
}
}

This config file will include all packages under ./typings, and no
packages from ./node_modules/@types

You can easily test it like:

tc –init

Create a index.d.ts file inside @types/index.d.ts, and put code below in it:

declare interface Foo {
Bar: string;
}

In the root folder, create a new index.ts file and inside the code-editor (Eg. VSCode), test it:

let foo:Foo;
foo. // you can see code-completion

p.s:
It doesn’t matter if you put the code inside @types or not, TypeScript automatically will find them. You can manually define the path for typeRoots as well but don’t forget to configure it to looks for @types inside node_modules.

[Vue.js] How to use vue-i18n translate function in script part of component

I’m using laravel-vue-i18n-generator package to handle text translation in vuejs component in my laravel project. I’ve set up app.js like below:

import VueInternationalization from ‘vue-i18n’;
import Locale from ‘./vue-i18n-locales.generated’;

Vue.use(VueInternationalization);

const lang = ‘fa’;

const i18n = new VueInternationalization({
locale: lang,
messages: Locale
});

const app = new Vue({
el: ‘#app’,
i18n,
});

And in component:

<template>

<a href=”#” class=”tip” title=”” :title=”$t(‘component.delete.title’)” @click.prevent=”deleteAction”>
<i :class=”icon”></i>
</a>
</template>

<script>
import swal from ‘sweetalert’;
import axios from ‘axios’;

export default {
inject: [‘$i18n’],
props:{
endpoint: {
type: String,
required: true,
},
icon: {
type: String,
default: ‘fa fa-trash’
},
message: {
type: String,
default: this.$i18n.t(‘component.delete.are_you_sure’),
},
confirm: {
type: String,
default: this.$i18n.t(‘component.delete.confirm’),
},
cancel: {
type: String,
default: this.$i18n.t(‘component.delete.cancel’),
},
success: {
type: String,
default: this.$i18n.t(‘component.delete.success’),
},
failed: {
type: String,
default: this.$i18n.t(‘component.delete.failed’),
},
},
mounted() {
console.log(this);
},
methods:{
deleteAction(){
const vm = this;
swal({
text: this.message,
buttons: {
catch: {
text: this.confirm,
value: “delete”,
},
cancel: this.cancel
},
dangerMode: true
}).then(name => {
if (!name) return false;

axios.delete(vm.endpoint)
.then(function (response) {
swal( vm.$i18n.t(‘component.delete.congrats’),vm.success, ‘success’).then(() => {
location.reload();
});
})
.catch(function (error) {
swal( vm.$i18n.t(‘component.delete.error’), vm.failed, ‘error’);
});
});
}
}

}
</script>

<style scoped>

</style>

Fortunately $t(‘component.delete.title’) works correctly on template part, but in script part, I’ve got this error:

Uncaught TypeError: Cannot read property ‘t’ of undefined

Where do I go wrong?

Solution :

This works for me.

there is a locales folder with index.js importing the two language files im using,
in this file add.

global.$t = Vue.t

Referred to in the script part directly as

return $t(‘backend.faq.main’)

[Vue.js] Open modal dialog on event bus event

I’ve created a backend and am now trying to build a frontend, using it. I’m very new to Vue.js and am having a hard time telling it to do what I want; probably because of missing some basic concepts. Hopefully someone can point me in the right direction.

The App.vue.js groups following components: Header, main section (routed), footer and a modal login dialog.
The issue I’m trying to solve is to display the modal login dialog when clicking the Login button (which lives in the header component); currently, nothing besides the messages being logged happens.
For this I’ve created an event bus and am firing an event:

export default {
name: ‘SppdTeamTunerHeader’,
methods: {
emitShowLoginDialogEvent () {
EventBus.$emit(‘ShowLoginDialog’, true)
}
}
}

Emitting the event works as I can see in the vue.js DevTools for Chrome.

Here’s the complete code of App.vue:

<template>
<div id=”app”>
<SppdTeamTunerHeader/>
<router-view></router-view>
<SppdTeamTunerFooter/>

<LoginDialogModal
v-show=”isLoginDialogVisible”
/>
</div>
</template>

<script>
import SppdTeamTunerHeader from ‘@/components/TheHeader’
import SppdTeamTunerFooter from ‘@/components/TheFooter’
import LoginDialogModal from ‘@/components/LoginDialogModal’
import { EventBus } from ‘@/common/EventBus’

export default {
name: ‘App’,
components: {
SppdTeamTunerHeader,
SppdTeamTunerFooter,
LoginDialogModal
},
data: function () {
return {
isLoginDialogVisible: false
}
},
mounted () {
EventBus.$on(‘ShowLoginDialog’, function (isVisible) {
console.log(‘Setting ShowLoginDialog isVisible=’ + isVisible + ‘. isLoginDialogVisible=’ + this.isLoginDialogVisible)
if (isVisible) {
this.isLoginDialogVisible = true
} else {
this.isLoginDialogVisible = false
}
console.log(‘Finished setting isLoginDialogVisible=’ + this.isLoginDialogVisible)
})
},
destroyed () {
EventBus.$off(‘ShowLoginDialog’)
}
}
</script>

When checking the console, following is being printed when clicking the login button:

Setting ShowLoginDialog isVisible=true. isLoginDialogVisible=undefined
Finished setting isLoginDialogVisible=true

The value logged for isLoginDialogVisible can’t come from the variable defined in the data function as it prints undefined, whereas it has been defined as false (I guess that’s my main problem).

I’ve read quite a few articles about the subject, e.g:

https://codingexplained.com/coding/front-end/vue-js/why-components-data-properties-must-be-functions
https://vuejs.org/v2/guide/instance.html#Data-and-Methods

The modal dialog example I’ve based the implementation comes from here: https://alligator.io/vuejs/vue-modal-component/

Solution :

This is happening because you are not using an Arrow function. Instead of a plain function, use arrow function like this:

mounted () {
// Note the use of arrow function.
EventBus.$on(‘ShowLoginDialog’, (isVisible) => {
// .. All the code
})
}

If you use plain function function () {}, then this pointer is not accessible within inner function. Arrow function will lexically bind this pointer to mounted() function’s this context. So use an arrow function i.e. () => {};

Note: If you insist on using plain old function syntax then use closure variable to keep track of this pointer:

mounted () {

// Assign this pointer to some closure variable
const vm = this;

EventBus.$on(‘ShowLoginDialog’, function (isVisible) {
console.log(‘Setting ShowLoginDialog isVisible=’ + isVisible + ‘. isLoginDialogVisible=’ + vm.isLoginDialogVisible)
if (isVisible) {
vm.isLoginDialogVisible = true
} else {
vm.isLoginDialogVisible = false
}
console.log(‘Finished setting isLoginDialogVisible=’ + vm.isLoginDialogVisible)
})
}

This has nothing to do with Vue.js. It is a typical JavaScript behavior.

Solution 2:

I believe the listener for the EventBus events needs to be accessible to App. Right now EventBus and App are two separate instances. You could mount the event handler inside App like this:

mounted () {
EventBus.$on(‘ShowLoginDialog’, function (isVisible) {

});

[Vue.js] Break Promise in Vuex Action on API error

This is probably an issue of using the wrong pattern to accomplish what I’m needing, so either an answer of what pattern (and what that pattern is) I should be using or what would solve my current pattern would be greatly appreciated!

there is use case where I need to wait for 1 to many API calls to successfully complete before routing the user to a different page/view… Here’s what I’m doing:

// Vuex action
[POST_NEW_INVOICE_UPDATE]: ({ commit }, update) => {
return apiEndpoints
.postNewInvoiceUpdate(update)
.then(() => {
app.$Progress.finish()
app.$Toastr.success(‘Invoice flagged’)
})
.catch((error) => {
console.error(error)
app.$Progress.fail()
app.$Toastr.error(‘There was an issue submitting the request’, ‘Request error’)
})
},

// In component
flag () {
// … simplifying for TLDR
const promises = []
flagSelections.forEach(selection => {
// … simplifying for TLDR
promises.push(this.$store.dispatch(‘POST_NEW_INVOICE_UPDATE’, parameters))
})

Promise.all(promises)
.then(() => {
// Route to next invoice in previous search, if search exists
// … simplifying for TLDR
})
.catch((error) => {
console.error(error)
})
},

I’m creating an array of the action, POST_NEW_INVOICE_UPDATE, and calling Promise.all on that array. the .then chain to break when an error is caught by the .catch in the action, becuase I don’t want to route my users until the APIs have been successful.

I believe I read in MDN that .then continues to chain even if an error is caught, but I obviously need something to prevent my user from being routed before the APIs are all successful.

I imagine I’m just using a dumb, self-created pattern and am not using Vuex actions correctly, so any help in the right direction would be appreciated!

EDIT: I forgot something important! If I take the code from the action and put it in promises.push instead of the dispatch, the code operates as needed, but I hate breaking the pattern of using Vuex for a single use-case.

Solution :

First off, I wouldn’t use Vuex purely to make API calls. The purpose of Vuex is to manage a global state, and I can see here that you’re not even using commit to mutate the state at all. You can abstract the API into the own objects or functions without needing Vuex. But it’s possible you just trimmed the code down and you actually are calling commit, so I’ll stick with that assumption.

Furthermore, it’s anti-pattern for Vuex to be making calls like app.$Progress.fail(). Vuex should know nothing about the components or UI, its sole job is to manage global state.

Here’s how I would structure it:

async flag() {
const promises = [];

flagSelections.forEach(selection => {
promises.push(postNewInvoiceUpdate(parameters));
});

try {
await Promise.all(promises);
app.$Progress.finish();
app.$Toastr.success(‘Invoice flagged’);
} catch (e) {
console.error(error);
app.$Progress.fail();
app.$Toastr.error(
‘There was an issue submitting the request’,
‘Request error’
);
}
},

If any of the Promises fail, the code in the catch block will be executed. Promise.all means all Promises must resolve, not just some of them. And I would just import postNewInvoiceUpdate from a separate module. There’s no need to use Vuex for this.

[Vue.js] Vue2-leaflet map not showing properly in BoostrapVue modal

Here’s my problem - a Vue2 leaflet map does not render correctly in Bootstrapvue.js modal.

Here’s what it looks like visually (it should show just the ocean)

<template>
<div>
<b-modal size=”lg” :visible=”visible” @hidden=”$emit(‘clear’)” title=”Event details”>
<div class=”foobar1”>
<l-map :center=”center” :zoom=”13” ref=”mymap”>
<l-tile-layer :url=”url” :attribution=”attribution”></l-tile-layer>
<l-marker :lat-lng=”center”></l-marker>
</l-map>
</div>

<template slot=”modal-footer”>
<b-btn variant=”danger” @click=”deleteEventLocal(event.id)”>Delete</b-btn>
</template>
</b-modal>
</div>
</template>

<script>
import * as moment from “moment”;
import { LMap, LMarker, LTileLayer } from “vue2-leaflet”;
import { deleteEvent } from “./api”;
import “vue-weather-widget/dist/css/vue-weather-widget.css”;
import VueWeatherWidget from “vue-weather-widget”;

export default {
data() {
return {
center: L.latLng(event.latitude, event.longitude),
url: “http://{s}.tile.osm.org/{z}/{x}/{y}.png”,
attribution:
‘© <a href=”http://osm.org/copyright">OpenStreetMap</a> contributors’
};
},
props: {
visible: {
type: Boolean
},
event: {
required: true,
type: Object
}
},
methods: {
async deleteEventLocal(id) {
await deleteEvent(id);
this.$emit(“refresh”);
this.$emit(“clear”);
}
},
components: {
weather: VueWeatherWidget,
LMap,
LMarker,
LTileLayer
}
};
</script>

As you can see there aren’t any CSS rules that could make the map spill outside the modal as it does. Which is weird.

I’m kinda asking this question to answer it myself as I couldn’t find a solution before.

Solution :

There were 3 issues because of which this was happening.

First - I forgot to load the leaflet css into main.js - this is why the leaflet map was somehow outside the modal.

//main.js
import ‘@babel/polyfill’;
import vue.js from ‘vue’;
import ‘./plugins/bootstrap-vue’;
import App from ‘./App.vue’;
import router from ‘./router’;
import store from ‘./store’;
//above imports not important to this answer

import ‘leaflet/dist/leaflet.css’; //<————–add this line

Vue.config.productionTip = false;

new Vue({
router,
store,
render: h => h(App),
}).$mount(‘#app’);

Now the map may disappear. Set a width and height on the l-map component’s container.

<div class=”foobar1”>
<l-map :center=”center” :zoom=”13”>
<l-tile-layer :url=”url” :attribution=”attribution”></l-tile-layer>
<l-marker :lat-lng=”center”></l-marker>
</l-map>
</div>

<style lang=”scss”>
.foobar1 {
width: 100%;
height: 400px;
}
</style>

Now the map will render within the modal but if you move the map’s view, you’ll see that leaflet does not download the maps’ squares in time.
You will see something like this:

To fix this, create an event handler on b-modal for the @shown event.

<b-modal
size=”lg”
:visible=”visible”
@hidden=”$emit(‘clear’)”
title=”Event details”
@shown=”modalShown”
\>

I called mine modalShown.

Then, add a ref attribute to the l-map. I called mine mymap.

<l-map :center=”center” :zoom=”13” ref=”mymap”>
<l-tile-layer :url=”url” :attribution=”attribution”></l-tile-layer>
<l-marker :lat-lng=”center”></l-marker>
</l-map>

Then create a modalShown method in the vue.js methods for the view/component and call invalidateSize() inside. I don’t know why it works. invalidateSize is part of native leaflet API (vue2leaflet is just a wrapper), and we’re calling it in this method.

export default {
data() {
//some data here
}

methods: {
modalShown() {
setTimeout(() => {
this.$refs.mymap.mapObject.invalidateSize();
}, 100);
}
}
}

Now everything should be fine - the map should not spill outside the modal, the map should be visible (duh) and the map squares should be downloaded when they are within the map body.

Here’s my full code, it contains some stuff specific to my app but overall it contains all of the code snippets above.

[Vue.js] Ag grid expand/collapse with pagination

I’m using detail-master feature and pagination. When I expend most bottom row, detail grid should stay on the same page as master row. Any good examples on how to do that? Thanks in advance.

Solution :

Found a moderately satisfying solution: This only works if I set paginationPageSize manually; with paginationAutoPageSize=true bottom row expansion still goes to another page.

onRowGroupOpened(event) {
if (event.node.expanded) {
this.gridOptions.api.paginationSetPageSize(++this.pageSize);
} else {
this.gridOptions.api.paginationSetPageSize(–this.pageSize);
}
},

[Vue.js] Laravel & Vue warning issue

there is worked on Laravel & vue.js js project.

This is Laravel code

The code works well but there is a warning in developer mode (inspect)

Laravel View code

@extends(‘layouts/app’)

@section(‘content’)

<div id=”app”>
</div>

@endsection

app.js code

const router = new VueRouter({ mode: ‘history’, routes: routes});
const app = new Vue(Vue.util.extend({ router }, App)).$mount(‘#app’);

app.js:74791 [vue.js warn]: Cannot find element: #app
warn @ app.js:74791
query @ app.js:79817
./node_modules/vue/dist/vue.common.dev.js.Vue.$mount @ app.js:86018
./resources/js/app.js @ app.js:86329
__webpack_require__ @ app.js:20
0 @ app.js:86576
__webpack_require__ @ app.js:20
(anonymous) @ app.js:84
(anonymous) @ app.js:87
app.js:74791 [vue.js warn]: Property or method “single” is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.

found in

-–> <Overlap> at resources/js/components/OutwardComponent.vue
<Root>

Solution :

the div that needs to reference the vue.js should be in Layout file,
It might be possible that the div is rendering after the vue.js Initialization.
Put <div id=”app”></div> in layouts/app file and see if its gone or not.

[Vue.js] How to link routes list with store variable?

Is there any way to link routes list:

// router.js
export default new Router({
routes: [
{ path: ‘/‘, component: Page },
{ path: ‘/page1’, component: Page1 },
{ path: ‘/page2’, component: Page2 },
]
})

…to the variable in store:

// store.js
export default new Vuex.Store({
state: {
routes_list: []
}
})

?

Solution :

You would need to add a getter for the list. Something like:

export default new Vuex.Store({
state: {
routes_list: []
},
getters: {
routesList: state => {
return state.routes_list;
}
}
})

Then you could import the Store in the router.js and use the created getter to receive the list:

// maybe the path is different
import Store from ‘@/store/index’;
export default new Router({
routes: Store.getters.routesList
})

I’ve didn’t tested the router code, maybe you need to do some correction.

[Vue.js] How to render a vnode (slot of a vue component) and mount it on an element?

For example, here we have a dialog component.

<dialog>
<div>
{data}
</div>
</dialog>

As we known, due to the stack context, it’s hard to make the dialog always be the topmost element.

So we need to mount the dialog element as a body’s child.

I tried this in dialog’s mounted hook.

var slot=this.$slots.default
var vm = new Vue({
render: ()=>slot
}
var div=document.createElement(‘div’)
document.body.append(div)
vm.mount(div)

The result is: it mounted successfully.

However, when I changed the data, the mounted vm didn’t change.

I wonder how to make it reactive or is there any other way to achieve this.

Solution :

Now that I can’t find any methods to solve this.
there is to read some open source ui framework’s source code because I know they do put the dialog in the body’s child level.

And I found that they do render the <slot>, but I can’t find any code rendered in the corresponding position and I can’t find any code they use to ‘remove’ it.

Then, I found a line of code, document.body.append(this.$el). when stupid. I didn’t realize that append will just remove the element from it’s original position and append it to the new position util I re-read the whole code once again.

I did think about this way, just append $el to somewhere. But when afraid that it’ll break the component down.

So, the solution is:

just define a normal vue.js component
ship the $el or child element to anywhere you want using element.append etc. after the component mounted
no need to remove the element manually when component is destroyed if you just ship the $el, vue.js will take care of it.