Vue Template - Making any URLs found in returned text string to a link - vue.js

I am working on a project that is Vue modular based (code used is: https://github.com/mishushakov/dialogflow-web-v2/blob/bc3ce7d7cf8e09a34b5fda431590bd48cc31f66b/src/App.vue)
Linking to the file I think need to make the change to, have been trying but I don't really know Vue at all and had not luck.
The returned message is plain text for example: this is a test message, please visit https://wwww.google.com
What I am trying to do, is from that text string, if a URL found is to create a link from that found URL
<RichComponent><RichBubble v-if="message.queryResult.fulfillmentText" :text="message.queryResult.fulfillmentText" /></RichComponent>
Is what the current code is that returns the data.
Is there a best way to achieve this? Is there a core function maybe?
I have tried to npm install linkify but cannot seem to get it working so maybe a direct approach would be better?

You can use linkifyjs to convert links in a string into anchor tags. The linkifyjs/lib/linkify-string.js file augments the String prototype with a linkify() method.
<template>
<p v-html="msg.linkify()"></p>
</template>
<script>
import 'linkifyjs/lib/linkify-string' // side effect: creates String.prototype.linkify
export default {
props: ['msg'],
}
</script>
It also exports that method if you prefer an explicit call:
<template>
<p v-html="linkify(msg)"></p>
</template>
<script>
import linkify from 'linkifyjs/lib/linkify-string'
export default {
props: ['msg'],
methods: {
linkify,
}
}
</script>

Related

Nuxt not automatically importing components from nested directory

In my nuxt app, components in nested directories are not automatically importing as expected. For some of my components i have something like the following:
vue 2.6.12, nuxt 2.15.0
components\ Directory structure
TopArea\
--SomeComponent.vue
<template>
<header class="header">
<div>Hello</div>
<SomeComponent />
</header>
</template>
No other component in the application has the name SomeComponent. In the example above i get the error: Unknown custom element: <SomeComponent> - did you register the component correctly? For recursive components, make sure to provide the "name" option.. I can get around the issue by specifying the directory name before the component filename (TopAreaSomeComponent), use the prefix option in nuxt.config, or by manually importing the component. This is confusing because the docs state:
Nested Directories
If you have components in nested directories such as:
components/baseButton.vue
The component name will be based on its own filename. Therefore, the component will be:
<button />
It goes on to say "We recommend you use the directory name in the filename for clarity". But that seems like a rule than a recommendation. If i don't use the directory name as part of the filename, dynamic imports are not working for components in nested directories.
Is this an error in the docs or am I reading it wrong?
Since Nuxt 2.15.0, components changed in the way they work as stated in this github issue.
Depending of you structure and how you want to handle your organization, you may edit your configuration accordingly to the migration guide available here: https://github.com/nuxt/components#v1-to-v2
Or you could also simply set the pathPrefix option to have all your components available without any prefix at all.
nuxt.config.js/ts
components: [
{
path: '~/components', // will get any components nested in let's say /components/test too
pathPrefix: false,
},
]
PS: this solution also works with Nuxt3.
This documentation actually do need an update, indeed: https://nuxtjs.org/docs/2.x/directory-structure/components#components-discovery
This is how it works: for a given page
<template>
<div>
<yolo-swag /> <!-- no need for <nested-yolo-swag /> here -->
</div>
</template>
And with the following file tree
Update for Nuxt3
Looks like this is the new official syntax
import { defineNuxtConfig } from 'nuxt'
export default defineNuxtConfig({
components: {
global: true,
dirs: ['~/components']
},
})
This may answered already. But to illustrate the solution to comers here here's the way according to docs:
<TopAreaSomeComponent />
if your components is nested deeply:
components / TopArea / SomeComponent.vue
https://nuxtjs.org/docs/directory-structure/components/#nested-directories

attribute binding in vue 3

I'm new to Vue and currently trying to dynamically change the video or image source link by passing the data in through a prop. I created a component with specific template structure that I would like to pass in the source from the main app.js page. I've tried binding it in both areas but unsure if I'm doing it correctly. I tried using regular divs and stuff to embed the video in app.js and it shows the content perfectly.
parent element contains 'Video' component-
<Video theme="IL" :vidSrc="srcIL.vid"></Video>
import Video from "./components/Video.vue";
export default {
name: "App",
components: {
Video
},
data() {
return {
srcIL: {
vid: "./assets/invi-lines/invisible-lines-film.mp4"
}
};
}
child 'Video component'
<template>
<div class="introVid top">
<video controls :src="vidSrc"></video>
</div>
</template>
<script>
export default {
props: ["theme", "vidSrc"]
};
</script>
This seems like you have it set up properly, and it is hard to know exactly what is causing the issues from the info provided, but I'm going to make a guess that it might be that the asset is not getting bundled.
I tried using regular divs and stuff to embed the video in app.js and it shows the content perfectly
I suspect you had something like:
<video controls src="./assets/invi-lines/invisible-lines-film.mp4"></video>
which would have taken the resource from the assets and packaged it for use.
see relative-path-imports for details.
You can try forcing these to load using require somewhere in the project, which will force the compiler to copy the asset, but really, if you have dynamic assets (assuming there's more than a handful and they can change) you should have them in the public folder already, not in the source folder. So my recommendation is that you move the dynamic assets to the public folder (assuming that was your issue to begin with)

Vue won't render anything if there are *any* errors

I'm learning Vue, and I notice that when other people view their webpages, it mostly displays alright even if they haven't finished the code. This is the behavior I'm used to from vanilla html/css/javascript.
But every time I have any problem with a component, e.g. undefined variable, it breaks the whole component and nothing gets displayed. For example, in a Single File Component if I have
<template>
<form>
<label>Write the title:</label>
<input v-model="title"></input>
/* Bunch of other stuff */
<form>
</template>
<script>
export default {
data() {
return {
/* I forget to write title here */
}
}
}
</script>
<style>
</style>
The whole template won't get displayed. Why is this happening and how can I fix it? It makes development much harder.
Btw I'm using Vue CLI 3 and used Vue UI to create the project, and "npm run serve" to view the site.

How to insert content inside tinymce editor using vue js?

I want to insert content like <span class="some-class">text</span> inside tinymce editor using a button in vue js template. How could I accomplish that using the tinymce-vue wrapper?
Here's the code:
<template>
<tinymce-editor
api-key="my-api-key-here"
/>
<button #click="addContent">button</button>
</template>
import Editor from '#tinymce/tinymce-vue'
export default {
components: {
tinymceEditor: Editor
},
methods: {
addContent () {
tinymce.activeEditor.setContent('<span class="some-class">text</span>');
}
}
}
Edit:
I also installed tinymce using npm i tinymce --save and added the import import tinymce from 'tinymce/tinymce to the code above. Now I don't get the error 'tinymce' is not defined anymore, but the editor doesn't appear either.
If you want to use tinymce in vue with typscritt to set up your content and avoid the undefined error you need to import tinyMCE as
import { getTinymce } from '#tinymce/tinymce-vue/lib/cjs/main/ts/TinyMCE';
Then you can set your content
getTinymce().activeEditor.setContent('coucou');
In your event handler for the button click, you can call TinyMCE's .setContent() method to set editor content.
Here is a demo:
https://codesandbox.io/s/set-content-in-tinymce-in-vue-jzciu
Don't forget, tinymce-vue doesn't include the code for TinyMCE itself. You'll either have to use an API key (which you can get for free at tiny.cloud) or use a self-hosted installation of TinyMCE. (For more info, see Step 6, here: https://www.tiny.cloud/docs/integrations/vue/#procedure)
I finally gave up trying to get access to tinymce in Vue 3 component. It either undefined or if it is not undefined - setContent command just do nothing - no errors but still no content inserted.
I just used recommended for "#tinymce/tinymce-vue" way of data binding using v-model
It looks like this:
<Editor
v-model="someLocalVar"
api-key="no-api-key"
:init="{
plugins: 'lists link image table code help wordcount',
}"
/>
then
watch(someLocalVar, () => {
//do whatever you like with your someLocalVar
});
If you want to insert content into TinyMCE you should use its APIs to do so:
https://www.tiny.cloud/docs/api/tinymce/tinymce.editor/#setcontent
https://www.tiny.cloud/docs/api/tinymce/tinymce.editor/#insertcontent
For example:
tinymce.activeEditor.setContent('<span class="some-class">text</span>');
tinymce.activeEditor.insertContent('<span class="some-class">text</span>');

vue-apollo: GraphQL queries only run when using <ApolloQuery> tags. Never works in script code. this.$apollo.queries is empty

I know I'm probably missing something really super basic here, I'm trying to run a graphql query with vue-apollo... if I use tags, it works fine
If I try to run queries from inside my code, like in the basic examples in the docs (links below) then nothing happens. The server never receives any request, and this.$apollo.queries is empty.)
Basic examples from the docs:
https://akryum.github.io/vue-apollo/guide/apollo/#queries
https://vue-apollo.netlify.com/guide/apollo/queries.html#simple-query
I've defined the query in the "apollo" property/object... how do I actually execute it when the page loads? Note that I'm using typescript, which is why it's using a "get apollo()" method.
Here's my code...
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
export default class List extends Vue {
myQueryName='my default value';
get apollo() {
return {
myQueryName: {
query: require('../graphql/listMeta.graphql'),
// prefetch: true <-- tried with and without this
}
}
}
}
</script>
<template>
<div>
<!-- THIS DOESN"T WORK ... -->
queries are: {{this.$apollo.queries}} <!-- THIS JUST SHOWS AN EMPTY OBJECT: {} -->
<hr>
myQueryName value is: {{myQueryName}} <!-- THIS JUST SHOWS "my default value" -->
<hr>
<!--
THIS DOES WORK...
<ApolloQuery :query="this.apollo.myQueryName.query" >
<template slot-scope="{ result: { loading, error, data } }"></template>
</ApolloQuery>
-->
</div>
</template>
Note that this.$apollo.queries is empty in the template, probably a clue... but still no idea why its empty. From the docs and examples I've seen it should be populated from my get apollo data method.
Looks basically the same as https://github.com/OniVe/vue-apollo-typescript-example/blob/master/pages/index.vue as far as I can tell, I don't know what the difference is.
I've tried rebuilding the project from scratch multiple times (with and without nuxt), over teh course of months and many different versions of vue/nuxt/apollo/vue-apollo... the queries never run (from memory) unless I use tags.
What am I missing?
You are missing #Component decorator, it is needed to set initial properties of Vue component, so vue-apollo can detect it when component created and make a smartquery property.
import { Component, Vue } from 'vue-property-decorator'
import listMetaDocument from '../graphql/listMeta.gql'
#Component({
name: 'List',
apollo: {
listMeta: {
query: listMetaDocument
},
},
})
export default class List extends Vue { }