Vue3 vue-intersect not working with v-if? - vue.js

When I use
<intersect v-if="activated == true" #enter=" addImages();" > <div class="h-1 w-full border"></div> </intersect>
The intersect appears in the dom when the condition is met, but the intersect is not doing any method anymore when I scroll to it.
If I remove the if then I have the problem that with a big screen when the page loads, the intersect gets activated a couple of times while loading.
How to make the intersect work with v-if? what is the reason that its not working?
Here the code of the intersect component ( from this project vue-intersect):
import Vue from 'vue'
const warn = (msg) => {
if (!Vue.config.silent) {
console.warn(msg)
}
}
export default {
name: 'intersect',
abstract: true,
props: {
threshold: {
type: Array,
required: false,
default: () => [0, 0.2]
},
root: {
type: typeof HTMLElement !== 'undefined' ? HTMLElement : Object,
required: false,
default: () => null
},
rootMargin: {
type: String,
required: false,
default: () => '0px 0px 0px 0px'
}
},
mounted () {
this.observer = new IntersectionObserver((entries) => {
if (!entries[0].isIntersecting) {
this.$emit('leave', [entries[0]])
} else {
this.$emit('enter', [entries[0]])
}
this.$emit('change', [entries[0]])
}, {
threshold: this.threshold,
root: this.root,
rootMargin: this.rootMargin
})
this.$nextTick(() => {
if (this.$slots.default && this.$slots.default.length > 1) {
warn('[VueIntersect] You may only wrap one element in a <intersect> component.')
} else if (!this.$slots.default || this.$slots.default.length < 1) {
warn('[VueIntersect] You must have one child inside a <intersect> component.')
return
}
this.observer.observe(this.$slots.default[0].elm)
})
},
destroyed () {
this.$emit('destroyed')
this.observer.disconnect()
},
render () {
return this.$slots.default ? this.$slots.default[0] : null
}
}

It seems you're installing the old version of this component which is not compatible with Vue 3, try to uninstall the installed version and install the next one
npm uninstall vue-intersect --save
then
npm install vue-intersect#next --save

Related

TipTap Vue custom component selects the entire line, not the selected one

I will immediately introduce the custom extension Tag.js
import { mergeAttributes, Node } from "#tiptap/core";
import { VueNodeViewRenderer } from "#tiptap/vue-3";
import { markInputRule } from "#tiptap/core";
import { markPasteRule } from "#tiptap/core";
import Component from "~/components/Editor/Tag.vue";
const starInputRegex = /(?:^|\s)((?:\*)((?:[^*]+))(?:\*))$/;
const starPasteRegex = /(?:^|\s)((?:\*)((?:[^*]+))(?:\*))/g;
const underscoreInputRegex = /(?:^|\s)((?:_)((?:[^_]+))(?:_))$/;
const underscorePasteRegex = /(?:^|\s)((?:_)((?:[^_]+))(?:_))/g;
export default Node.create({
name: "vuetag",
group: "block",
content: "inline*",
selectable: true,
parseHTML() {
return [
{
tag: "tag",
},
];
},
renderHTML({ HTMLAttributes }) {
return ["tag", mergeAttributes(HTMLAttributes), 0];
},
addNodeView() {
return VueNodeViewRenderer(Component);
},
addInputRules() {
return [
markInputRule({
find: starInputRegex,
type: this.type,
}),
markInputRule({
find: underscoreInputRegex,
type: this.type,
}),
];
},
addPasteRules() {
return [
markPasteRule({
find: starPasteRegex,
type: this.type,
}),
markPasteRule({
find: underscorePasteRegex,
type: this.type,
}),
];
},
addCommands() {
return {
setTag:
() =>
({ commands }) => {
return commands.setNode(this.name);
},
};
},
});
Component Tag.vue
<template>
<node-view-wrapper>
<el-tag><node-view-content /></el-tag>
</node-view-wrapper>
</template>
<script>
import { NodeViewContent, nodeViewProps, NodeViewWrapper } from "#tiptap/vue-3";
export default {
components: {
NodeViewWrapper,
NodeViewContent,
},
props: nodeViewProps,
};
</script>
<style lang="scss"></style>
There is a text: Did you see that? That’s a Vue component. We are really living in the future.
Let's say I want the phrase Did you see that? specify as a tag. I highlight this phrase and click on the button, the event setTag() is triggered
The result I get is this:<tag>Did you see that? That’s a Vue component. We are really living in the future.</tag>
The problem is that here the whole one line becomes a tag, that is, inside the Tag component.Vue
And there should be such a result: <tag>Did you see that?</tag> That’s a Vue component. We are really living in the future.
As an el-tag, I took from https://element-plus.org/en-US/component/tag.html

How to render portable block from sanity in vue app

I'm testing around with sanity right now and I am trying to display portable text of sanity on my vue frontend. Sadly it does not work as expected.
So i use the npm package sanity-blocks-vue-component to render the portable text and the normal fetch function which is privided in the docs of sanity.
This is my file where I fetch it successfully but the SanityBlock does nothing:
<template>
<div :class="name">
<SanityBlocks :block="content.impressumContent" />
</div>
</template>
<script>
import { SanityBlocks } from 'sanity-blocks-vue-component';
import sanity from "../../sanity.js";
const query = `*[_type == "impressum"]{
impressumContent,
}
`
export default {
components: {
SanityBlocks
},
data() {
return {
name: 'p-impressum',
loading: true,
content: [],
}
},
created() {
this.fetchData();
},
methods: {
fetchData() {
this.error = this.impressum = null;
this.loading = true;
sanity.fetch(query).then(
(content) => {
this.loading = false;
this.content = content;
},
(error) => {
this.error = error;
}
);
}
}
}
</script>
And that's the scheme that I fetch:
export default {
name: 'impressum',
type: 'document',
title: 'Impressum',
fields: [
{
name: 'impressumContent',
title: 'Impressum Content',
type: 'array',
of: [
{
type: 'block'
},
]
}
]
}
I don't get my head around why this isn't working. Hopefully somone can help me.
Thaanks:))

Dropdown and Vuetify

I have installed fresh Vue.js and Vuetify.
For some reason, my tag, which is used for dropdown menu with autosuggest is not visible anymore. jQuery lib and select2 package are installed.
or are visible and working.
Is there a conflict with Vuetify? Maybe I forgot to install some package?
Even after I unhide my in inspector (by changing bg-color property) it is visible, but still not working.
How could I check, if the problem is with Vuetify?
How to check, whether it's a problem of some packages not installed?
<template>
<div class="information">
<div> <select style="display:block" id="location" data-placeholder="Von:" data-width="30%"></select>
</div>
</div>
</template>
<script>
import $ from 'jquery'
export default {
name: "HereAddressLookup",
data() {
return {
};
},
mounted() {
var options = {
minimumInputLength: 1,
ajax: {
url: 'https://autocomplete.geocoder.ls.hereapi.com/6.2/suggest.json',
delay: 250,
dataType: 'json',
data: function (params) {
return {
query: params.term,
apiKey: 'v35d7iIj8nuBconhXjWobmSTzQbz8tL99jhnDGTR-ds',
beginHighlight: '<b>',
endHighlight: '</b>',
country: 'DEU'
};
},
processResults: function (data) {
return {
results: $.map(data.suggestions, function (obj) {
return { id: obj.locationId, text: obj.label.split(', ').reverse().join(', ') };
})
};
}
},
escapeMarkup: function (markup) { return markup; }
};
$('#location').select2(options).on('select2:select', function (e) {
$.getJSON('https://geocoder.ls.hereapi.com/6.2/geocode.json', {
apiKey: 'v35d7iIj8nuBconhXjWobmSTzQbz8tL99jhnDGTR-ds',
locationId: e.params.data.id
}).done(function (data) {
var locn = data.Response.View[0].Result[0].Location;
var opts = {
apiKey: 'v35d7iIj8nuBconhXjWobmSTzQbz8tL99jhnDGTR-ds',
variant: 'normal.day'
};
});
});
},
}
</script>
How it should look:

Storybook.js (Vue) Docs Template Output

Using StoryBook.js, when I navigate to a component, view its "Docs" and click the "Show Code" button, why do I get code that looks like this...
(args, { argTypes }) => ({
components: { Button },
props: Object.keys(argTypes),
template: '<Button v-bind="$props" />',
})
...as opposed to this...
<Button type="button" class="btn btn-primary">Label</Button>
Button.vue
<template>
<button
:type="type"
:class="'btn btn-' + (outlined ? 'outline-' : '') + variant"
:disabled="disabled">Label</button>
</template>
<script>
export default {
name: "Button",
props: {
disabled: {
type: Boolean,
default: false,
},
outlined: {
type: Boolean,
default: false,
},
type: {
type: String,
default: 'button',
},
variant: {
type: String,
default: 'primary',
validator(value) {
return ['primary', 'success', 'warning', 'danger'].includes(value)
}
}
}
}
</script>
Button.stories.js
import Button from '../components/Button'
export default {
title: 'Button',
component: Button,
parameters: {
componentSubtitle: 'Click to perform an action or submit a form.',
},
argTypes: {
disabled: {
description: 'Make a button appear to be inactive and un-clickable.',
},
outlined: {
description: 'Add a border to the button and remove the fill colour.',
},
type: {
options: ['button', 'submit'],
control: { type: 'inline-radio' },
description: 'Use "submit" when you want to submit a form. Use "button" otherwise.',
},
variant: {
options: ['primary', 'success'],
control: { type: 'select' },
description: 'Bootstrap theme colours.',
},
},
}
const Template = (args, { argTypes }) => ({
components: { Button },
props: Object.keys(argTypes),
template: '<Button v-bind="$props" />',
})
export const Filled = Template.bind({})
Filled.args = { disabled: false, outlined: false, type: 'button', variant: 'primary' }
export const Outlined = Template.bind({})
Outlined.args = { disabled: false, outlined: true, type: 'button', variant: 'primary' }
export const Disabled = Template.bind({})
Disabled.args = { disabled: true, outlined: false, type: 'button', variant: 'primary' }
I thought I followed their guides to the letter, but I just can't understand why the code output doesn't look the way I expect it to.
I simply want any of my colleagues using this to be able to copy the code from the template and paste it into their work if they want to use the component without them having to be careful what they select from the code output.
For anyone else who encounters this issue, I discovered that this is a known issue for StoryBook with Vue 3.
As mine is currently a green-field project at the time of writing this, I put a temporary workaround in place by downgrading Vue to ^2.6.
This is OK for me. I'm using the options API to build my components anyway so I'll happily upgrade to Vue ^3 when Storybook resolve the above linked issue.
One of possible options is to use current workaround that I found in the GH issue mentioned by Simon K https://github.com/storybookjs/storybook/issues/13917:
Create file withSource.js in the .storybook folder with following content:
import { addons, makeDecorator } from "#storybook/addons";
import kebabCase from "lodash.kebabcase"
import { h, onMounted } from "vue";
// this value doesn't seem to be exported by addons-docs
export const SNIPPET_RENDERED = `storybook/docs/snippet-rendered`;
function templateSourceCode (
templateSource,
args,
argTypes,
replacing = 'v-bind="args"',
) {
const componentArgs = {}
for (const [k, t] of Object.entries(argTypes)) {
const val = args[k]
if (typeof val !== 'undefined' && t.table && t.table.category === 'props' && val !== t.defaultValue) {
componentArgs[k] = val
}
}
const propToSource = (key, val) => {
const type = typeof val
switch (type) {
case "boolean":
return val ? key : ""
case "string":
return `${key}="${val}"`
default:
return `:${key}="${val}"`
}
}
return templateSource.replace(
replacing,
Object.keys(componentArgs)
.map((key) => " " + propToSource(kebabCase(key), args[key]))
.join(""),
)
}
export const withSource = makeDecorator({
name: "withSource",
wrapper: (storyFn, context) => {
const story = storyFn(context);
// this returns a new component that computes the source code when mounted
// and emits an events that is handled by addons-docs
// this approach is based on the vue (2) implementation
// see https://github.com/storybookjs/storybook/blob/next/addons/docs/src/frameworks/vue/sourceDecorator.ts
return {
components: {
Story: story,
},
setup() {
onMounted(() => {
try {
// get the story source
const src = context.originalStoryFn().template;
// generate the source code based on the current args
const code = templateSourceCode(
src,
context.args,
context.argTypes
);
const channel = addons.getChannel();
const emitFormattedTemplate = async () => {
const prettier = await import("prettier/standalone");
const prettierHtml = await import("prettier/parser-html");
// emits an event when the transformation is completed
channel.emit(
SNIPPET_RENDERED,
(context || {}).id,
prettier.format(`<template>${code}</template>`, {
parser: "vue",
plugins: [prettierHtml],
htmlWhitespaceSensitivity: "ignore",
})
);
};
setTimeout(emitFormattedTemplate, 0);
} catch (e) {
console.warn("Failed to render code", e);
}
});
return () => h(story);
},
};
},
});
And then add this decorator to preview.js:
import { withSource } from './withSource'
...
export const decorators = [
withSource
]

how to fix blank page if i am using vue router with electron js?

I'm trying to use vue router with an application on an Electron JS. If I use a router on the render page, then the router work done. But I do not understand how to make the transition to the page, for example,- 'Settings' using the Tray. At attempt of transition the empty page opens.
I have prepared a working example of the project. This problem exists only build project. In development mode all work well.
This is my work example on github. Please need help.
git clone https://github.com/DmtryJS/electron-vue-example.git
cd electron-vue-example
npm install
npm run build
and run dist\win-unpacked\example_for_stackoverflow.exe
my main.js file
'use strict'
import { app, protocol, BrowserWindow, Menu, ipcMain, Tray } from 'electron'
import { format as formatUrl } from 'url'
const electron = require('electron');
const path = require('path');
const isDevelopment = process.env.NODE_ENV !== 'production';
let imgBasePath;
if(isDevelopment) {
imgBasePath = path.join('src','assets', 'img');
} else {
imgBasePath = path.join(path.dirname(__dirname), 'extraResources', 'img');
}
let win;
let tray;
protocol.registerStandardSchemes(['app'], { secure: true })
const trayIcon = path.join(__static, 'img', 'icon.png');
function createWindow () {
win = new BrowserWindow({
width: 800,
height: 600,
icon: trayIcon
})
routeTo(win, "")
win.on('closed', () => {
win = null
})
//убрать меню
win.setMenuBarVisibility(true)
win.on('show', function() {
tray.setHighlightMode('always')
})
win.on('hide', function() {
tray.setHighlightMode('never')
})
}
// Quit when all windows are closed.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (win === null) {
createWindow()
}
})
app.on('ready', () => {
createWindow()
win.webContents.openDevTools(); //открыть dev tools
createTray()
})
// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
if (process.platform === 'win32') {
process.on('message', data => {
if (data === 'graceful-exit') {
app.quit()
}
})
} else {
process.on('SIGTERM', () => {
app.quit()
})
}
}
function createTray()
{
let traiIconPath = path.join(imgBasePath, 'preloader_tray_icon.png')
tray = new Tray(traiIconPath)
const contextMenu = Menu.buildFromTemplate(
[
{
label: 'Settings',
type: 'normal',
click: function()
{
routeTo(win, "/settings")
let contents = win.webContents
contents.on('dom-ready', function()
{
if(!win.isVisible())
{
showWindow()
}
})
}
},
{
label: 'Exit',
type: 'normal',
click: function()
{
win = null
app.quit()
}
}
])
tray.setContextMenu(contextMenu)
tray.on('click', function() {
toggleWindow();
})
}
function showWindow() {
var position = getPosition();
win.setPosition(position.x, position.y, false)
win.show()
win.focus()
}
ipcMain.on('routerEvent', function(event, arg) {
routeTo(win, arg)
})
function routeTo(win, to) {
if (isDevelopment) {
win.loadURL(`http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}` + to)
} else {
win.loadURL(formatUrl({
pathname: path.join(__dirname, 'index.html' + to);,
protocol: 'file',
slashes: true
}))
}
}
And
router.js
import Vue from 'vue'
import Router from 'vue-router'
import Main from './../views/Main.vue'
import Settings from './../views/Settings.vue'
Vue.use(Router)
export default new Router({
//mode: 'history',
routes: [
{
path: '/',
name: 'home',
component: Main
},
{
path: '/settings',
name: 'settings',
component: Settings
}
]
})
You need to add created to the main Vue app check docs
// src/main.js
new Vue({
router,
render: h => h(App),
created() {
// Prevent blank screen in Electron builds
this.$router.push('/')
}
}).$mount('#app')
The solution for me was to remove the history mode in the vue router.
Sorry, but after one day of googling, I just found a solution. The case turned out to be
win.loadURL(formatUrl({
pathname: path.join(__dirname, 'index.html' + to);,
protocol: 'file',
slashes: true
}))
I delete formaUrl and everything works well
win.loadURL(path.join(__dirname, 'index.html' + to));
For me solution was this:
Check if app is running at addresses like this:
Local: http://x86_64-apple-darwin13.4.0:8080/
Network: http://localhost:8080/
Check if you can access x86_64..url in browser. If you are not seeing a webpage but can see it from localhost, then map 127.0.0.1 to x86_64-apple-darwin13.4.0 in hosts file. in mac its located in /etc/hosts in windows its in system32/drivers/etc.