How do I use outsourced and editable scripts in Nuxt.js? - javascript

I am currently developing a website with Nuxt. A certain javascript file should be editable after building to change the content of a table. Does anyone have an idea how I can do this?
Up to now I tried to include the javascript file as plugin without success. Furthermore, I also failed the attempt to swap the script as follows:
<!-- my-component.vue -->
<template>
<div>This is a Text!</div>
</template>
<script src="./my-outsourced-script.js"></script>
Currently my Code looks like this:
Bootstrap-Vue table:
<b-table
borderless
striped
hover
responsive
:sticky-header="stickyHeader"
:items="folderPermissions"
:fields="folderGroups"
>
</b-table>
Content to be swapped out:
export default {
data() {
return {
stickyHeader: true,
keyword: '',
sortBy: 'xxx',
sortDesc: false,
folderGroups: [
{
key: 'drive',
stickyColumn: true,
label: ' ',
isRowHeader: true
},
...
],
folderPermissions: [
{
drive: 'Some Text',
id: 0,
a: 1
},
...
]
}
}
}
My wish would be to have folderGroups and folderPermissions in the code shown above in an outsourced javascript file to easily modify them and see the changes on the website.

Like you do, or if you try to import your js file with your data like import { folderGroups, folderPermissions} from './my-outsourced-script.js, you cannot change the file without rebuild your nuxt app.
Try to build with your file as below:
{
"folderGroups": [
your datas
],
"folderPermissions": [
your datas
]
}
And dynamic import in your component:
data() {
folderGroups: [],
folderPermissions: []
},
mounted() {
this.$http.get('/js/my-outsourced-script.json').then((response) => { // no need `assets`
console.log(response.body)
this.folderGroups = response.body.folderGroups
this.folderPermissions = response.body.folderPermissions
}, function (error) {
console.log(error.statusText)
})
}

Related

Vue3: How to use Vuelidate v$ object in method

We are currently migrating an externally developed Vue 2 application to Vue 3 to fix issues with deprecated libraries and to be more 'future-proof'. Due to lack of knowledge about the Vue framework and the differences between Vue 2 and 3 (we read the migration guide), we are stuck on the use of the Vuelidate Next library to validate form fields.
We make use of:
Vue 3.2.13
#Vuelidate/core 2.0.0
#vuelidate/validators 2.0.0
The below code describes the situation as created by the original programmers in Vue 2 with minor adjustments. First we import the Vuelidate libraries and the form compoments we want to pass data and validation rules to. Next in setup(), we initiate Vuelidate by calling the useVuelidate hook and binding it to v$. Then in data(), the form fields, based upon a JSON schema, are defined. In validations(), we define a single rule for the 'nameEng' form field. Finally created() calls upon the setValidation method from the methods section.
<template>
<div v-if="facility">
{{ /* When we echo v$ we do get the full object */ }}
{{ v$ }}
<form #submit.prevent>
<component v-for="field in fields" :is="field.type" :key="field.id" :value="facility.fieldValues[field.id]"
:path="[field.id]" :context="{ resource: 'facilities', institutionId: facility.institutionId }"
:label="field.label" :fields="field.fields" :editable="editable" v-bind="{ ...field.options }" />
</form>
</div>
</template>
<script>
import useVuelidate from '#vuelidate/core';
import { fetchInstitution } from '#/services/institutionsService';
import FieldRow from '#/modules/core/components/ui/formElements/FieldRow.vue';
/* The JSON schema fields aka:
{
"general": [
{
"type": "FieldRow",
"id": "nameEng",
"label": "Facility name (English)",
"options": {
"field": "StringField",
"fieldOptions": {
"errorMessage": "Please fill in a name for this facility"
}
}
},
}
*/
import fields from '../schemas/fields.json';
export default {
components: {
FieldRow,
},
props: {
facility: {
type: [Object, Array],
},
editable: {
type: Boolean,
default: false,
},
},
setup() {
const v$ = useVuelidate();
return { v$: v$ };
},
data() {
return {
fields: fields.general,
};
},
validations() {
return {
facility: {
fieldValues: {
nameEng: {
required,
},
},
},
};
},
created() {
this.setValidation();
},
methods: {
setValidation() {
this.fields = fields.general.map((field) => {
if (field.options.fieldOptions?.errorMessage) {
/* Returns empty object: {} */
console.log(this.v$);
field.options.fieldOptions.validation = this.v$.facility.fieldValues[field.id];
}
return field;
});
},
},
};
</script>
The setValidation method needs to add the validation rules to the data which gets passed on to a form field component as props. However, when trying to access the v$ in the method, it is a completely empty object. We expected to be able to call v$.facility to get the rule set, but this logically results in an undefined. Contrary, when we echo v$ in the HTML template, we do get the full object returned including the facility rule set.
Our questions would be: why can we not use the v$ object in the methods section like this? should this method still be the correct way achieve the desired result in Vue 3?
Thanks in advance!
~ Tom

iterating over data including image in Gatsby

In Gatsby I would like to iterate over an array, which contains objects. One of the properties of each object would be an image. I would like to be able to use Gatsby Image.
Here is one example of when I'd like to do so: a page on a website with a gallery of images, each image opens a particular associated video when clicked. Perhaps I'd like 20, 50, or even 100+ objects in the array:
const videos = [
{
id: 1,
name: 'Festival 2018',
url: 'https://www.youtube.com',
img: // HOW TO ACHIEVE?
},
// Many more objects
]
videos.map((item) => {
return (
<Img
key={item.id}
fluid= // HOW TO ACHIEVE?
alt={item.name}
onClick={() => openPlayer(item.url)}
/>
)
})
I understand how to query for single images with GraphQL; or how to query multiple images and use aliases; or how to query all images from a folder. But I have't worked out how to achieve my goal. There's probably a better way. Thanks in advance.
To use internal images in gatsby-image you need to allow Gatsby and their transformers and sharps to know where the images are located using the gatsby-source-filesystem. This will create queryable nodes from your images and will allow you to use gatsby-image with them.
Applied to your case, you need to put all images in the same folder, let's say /src/images and:
const path = require(`path`)
module.exports = {
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: path.join(__dirname, `src`, `images`),
},
},
`gatsby-plugin-sharp`,
`gatsby-transformer-sharp`,
],
}
There, your JSON object will look like:
const videos = [
{
id: 1,
name: 'Festival 2018',
url: 'https://www.youtube.com',
img: '/relative/path/to/your/image.extension',
extension: 'png'
},
// Many more objects
]
Note: thanks John for the clarification about the extension field. Source: https://stackoverflow.com/a/56012718/13714522
In your case, since you are using a JSON-based source, you will need to add the gatsby-transformer-plugin. The configuration will look like:
module.exports = {
plugins: [
`gatsby-transformer-json`,
{
resolve: `gatsby-source-filesystem`,
options: {
path: `./src/data/`,
},
},
],
}
Note: assuming that the JSON is placed in /src/data
Also assuming that your JSON file is named data.json, if everything is properly set, Gatsby will create a GraphQL node called allDataJson. Then you only last to create a query (page query or static query) with the following content:
{
allDataJson {
edges {
node {
name
url
id
img {
childImageSharp {
fluid(maxWidth: 1000, quality: 100) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
}
Note: check your exact query in the localhost:8000/___graphql playground
If your paths are correct, Gatsby will create the childImageSharp node which will allow you to use your own internal images within gatsby-image feature. Since your queried data is stored inside props.data, your final loop should look like:
props.data.allDataJson.edges.node.map((item) => {
return (
<Img
key={item.id}
fluid={item.img.childImageSharp.fluid}
alt={item.name}
onClick={() => openPlayer(item.url)}
/>
)
})

How to add multiple pages in grapesjs?

I want to include multiple pages in grapesjs framework.
Grapesjs now supports pages using PageManager. you can have a look at the API documentation here https://grapesjs.com/docs/api/pages.html
The way to do it is
const editor = grapesjs.init({
....
pageManager: {
pages: [
{
id: 'page-id',
styles: `.my-class { color: red }`, // or a JSON of styles
component: '<div class="my-class">My element</div>', // or a JSON of components
}
]
},
})
You can add,remove , select the pages by using the methods from grapesjs.Page.

Custom background color in Monaco editor?

Looking through the Monaco examples and typings, it looks like themes can be configured via the defineTheme API. I'm trying to apply a VSCode theme to a Monaco instance, and am struggling with how to set the background color (for the whole editor, not just for a token).
Rules are defined as an array of objects with this shape:
IThemeRule {
token: string;
foreground?: string;
background?: string;
fontStyle?: string;
}
What should token be for setting the editor background?
More generally, is there a good way to apply this theme to a Monaco instance, without ripping out theme parsing logic from VSCode source? After a quick attempt to rip out the logic, it seems like a simple custom parser (ie. parse JSON theme definition -> flat list of IThemeRules) is the better way to go.
You can define your own theme and change the editor.background in colors option
monaco.editor.defineTheme('my-dark', {
...,
colors: {
"editor.background": '#394555'
}
});
You can define your theme like this
const theme = {
base: 'vs',
inherit: true,
rules: [
{ token: 'custom-info', foreground: 'a3a7a9', background: 'ffffff' },
{ token: 'custom-error', foreground: 'ee4444' },
{ token: 'custom-notice', foreground: '1055af' },
{ token: 'custom-date', foreground: '20aa20' },
]
}
and then apply it like this
monaco.editor.defineTheme('myTheme', theme)
var editor = monaco.editor.create(document.getElementById('container'), {
value: getCode(),
language: 'myCustomLanguage',
theme: 'myTheme'
});

React Component - Add custom functionality to npm package

I have an app which pretty much looks like this:
class App extends React.Component {
constructor (props) {
super(props)
this.state = {
tags: [
{ id: 1, name: "Apples" },
{ id: 2, name: "Pears" }
],
suggestions: [
{ id: 3, name: "Bananas" },
{ id: 4, name: "Mangos" },
{ id: 5, name: "Lemons" },
{ id: 6, name: "Apricots" }
]
}
}
handleDelete (i) {
const tags = this.state.tags.slice(0)
tags.splice(i, 1)
this.setState({ tags })
}
handleAddition (tag) {
const tags = [].concat(this.state.tags, tag)
this.setState({ tags })
}
render () {
return (
<ReactTags
tags={this.state.tags}
suggestions={this.state.suggestions}
handleDelete={this.handleDelete.bind(this)}
handleAddition={this.handleAddition.bind(this)} />
)
}
}
It's based on this npm module.
I am not sure if I am missing something, but when I type in a tag, whilst I do see the suggestions pop up, I would also like to be able to press the TAB key and autocomplete the rest of the tag, whenever there is only one option left. Similar to the stackoverflow tag functionality.
My main question is this: How could I use a package like this, installed via npm, and extend its functionality? What would I do to make this my own, change things around etc.? I do not want to fiddle around in my npm modules folder!
You can fork the plugin and install it in your project as below
npm i {github_project_link}
If you want to contribute to the community. You can raise PR to the origin repo.

Categories