Vue 2.6 with Rollup: import component by variable name - javascript

I am trying to add dynamic routes to my vue router (using router.addRoute()). It works so far, but I get a problem as soon as I try to set a component for my dynamic route.
This is the code that works:
var name = "reports";
var path = "reports/foo";
var item = {
name: name,
path: path,
component: () => import( "../pages/reports/Reports_Foo.vue" )
};
When calling the page it correctly loads the content of my Reports_Foo.vue
But when I want to load the vue file dynamically, like this:
var filename = "Reports_Foo";
var name = "reports";
var path = "reports/foo";
var item = {
name: name,
path: path,
component: () => import( "../pages/reports/"+filename+".vue" )
};
It no longer works and I get the following javascript error:
TypeError: Failed to fetch dynamically imported module: https://localhost:123456/js/pages/reports/Reports_Foo.vue
Why? Do you know a way to fix this ?
Edit: I'm using rollup to convert the files into chunks and then reference them.

Try explicitly loading the default export:
var item = {
name: name,
path: path,
component: async () => (await import("../pages/reports/"+filename+".vue")).default
}

Related

How to import a list from other .js file to my main.js file?

This is just an example from Ania kubow's Climate change API.
My question is : i have a list like this but it is more larger and long. I want to store that list in another file like "exampleList.js" then i want to import it to my main.js file.
const newspapers = [
{
name: 'cityam',
address: 'https://www.cityam.com/london-must-become-a-world-leader-on-climate-change-action/',
base: ''
},
{
name: 'thetimes',
address: 'https://www.thetimes.co.uk/environment/climate-change',
base: ''
},
{
name: 'guardian',
address: 'https://www.theguardian.com/environment/climate-crisis',
base: '',
},
{
name: 'telegraph',
address: 'https://www.telegraph.co.uk/climate-change',
base: 'https://www.telegraph.co.uk',
},
{
name: 'nyt',
address: 'https://www.nytimes.com/international/section/climate',
base: '',
},
{
name: 'latimes',
address: 'https://www.latimes.com/environment',
base: '',
},
]
Then i want to call it here instead of writing it in the same file (main.js) i dont want the code to look messy and too long. Actually i have more lists (probably 3 lists each has more than 100 address, base, name) i want to store them in different files.
app.get('/news/:newspaperId', (req, res) => {
const newspaperId = req.params.newspaperId
const newspaperAddress = newspapers.filter(newspaper => newspaper.name == newspaperId)[0].address
const newspaperBase = newspapers.filter(newspaper => newspaper.name == newspaperId)[0].base
axios.get(newspaperAddress)
.then(response => {
const html = response.data
const $ = cheerio.load(html)
const specificArticles = []
$('a:contains("climate")', html).each(function () {
const title = $(this).text()
const url = $(this).attr('href')
specificArticles.push({
title,
url: newspaperBase + url,
source: newspaperId
})
})
res.json(specificArticles)
}).catch(err => console.log(err))
})
I have tried to create a list file then i tried the statement import:
import exampleList from (./src/exampleList.js)
it says that i need to add "type": "module" to my package.json. i did that but it still not working, it says that i cannot import a statement from module . i also tried to run the app with .mjs and --node-experimental ... same thing, not working.
Firstly, make sure you are exporting the list that you have. Also, I recommend to store the data in a JSON format.
Secondly, regarding the error that you are facing
add "type": "module" to package.json
check out the main answer on this question
const newspapers = ["hello"]; module.exports = newspapers;
use this to export your data from the file and
use const newspaper = require("./src/exampleList") to import the file and can use the data in the other file.

Generate new page after slug

I am building a NextJS application, currently I am using getStaticPaths and getStaticProps to build the static pages, doing the necessary requests for them.
So I want to build all the pages following this url: challenge/[slug]/ and for each slug that corresponds to an id I want to have a applications page like this: challenge/[slug]/applications to archive this I builded a file [...slug] inside /pages/challenge
Inside that file I have the following code to handle the static generation:
export async function getStaticPaths() {
const response: any = await getPrograms()
const paths = response.results.map(result => {
return { params: { slug: [result.id.toString()] } }
})
return { paths, fallback: true }
}
export async function getStaticProps({ params }) {
const res = await getProgram(params.slug[0])
const stages = await getStages(params.slug[0])
return { props: { program: res, stages: stages }, revalidate: 1 }
}
this solution works for /challenge/[slug], but the /challenge/[slug]/applications receives a 404, how can I render a specific application page for the slug?
I tried to add a second position to the slug array, but if I do it I can just render /challenge/[slug]/applications and not /challenge/[slug]
Any advice?
Thanks!
Firstly, You need to create a FOLDER named [slug]. Then, Create a FILE named applications.js. Lastly, copy and paste that code into this page.
__ challenge
|__ [slug]
|__ applications
In this page you can get or set slug as your desired parameter.

How to load an external js file and use their data in reactjs?

I'm doing a react project using create-react-app and my current goal is to load an external js file (that is hosted in iis) and use their data.
I'm getting this file throught a script in index.html like:
<script type="text/javascript" src="http://localhost:5000/GetJsFile"></script>
Example of my js file:
var data = {
vars: {
id: ****,
user ******,
name: *******,
date: *******,
}
//...
}
My question is: how can I use/access the data from js file inside a component of react js?
In your utils.js page
you must change your code to this shape:
utils page
const data = {
vars: {
id: ****,
user ******,
name: *******,
date: *******,
}
//...
}
export default data;
and after that in other component that you want to use this data write this code:
import data from '../../../../utils';
...
console.log('data', data);
The problem with loading the JSON's data from the html file directly is that it will not be available for your react code to use.
Since you are loading it from an external source, you need to use something like fetch, axios or superagent to retrieve it.
You can either use async/await or promises.
async function loadJsonFromExternal() {
const dataFromJSON = await axios.get('http://localhost:5000/GetJson');
return dataFromJSON;
}
Say you have your component.js file with something like this:
import React, { useEffect } from 'react';
export default function CoolComponent (props) {
let myName = 'Enigma';
useEffect(() => {
loadJsonFromExternal()
.then((result) => { myName = result.name });
}, [])
return (
<div>My name is: {myName}</div>
)
}
That would be the approach to do.

Read contents of file into array inside vue component

Inside my media.txt file, I have:
"https://www.dropbox.com/s/******/687.jpg?dl=0",
"https://www.dropbox.com/s/******/0688.jpg?dl=0
I have the following Vue carousel component:
<template>
<section>
<v-card
class="mx-auto"
color="#26c6da"
dark
max-width="1200"
>
<v-carousel>
<v-carousel-item v-for="(item,i) in items" :key="i" :src="item.src"></v-carousel-item>
</v-carousel>
</v-card>
</section>
</template>
<script>
var cache = {};
// const images = require.context('../static/', false, /\.png$|\.jpg/);
// const images = require.context('../static/', false, /\.png$|\.jpg|\.mp4/); // WORKING
const images = require.context('../static/media.txt', false, /\.png$|\.jpg|\.mp4/);
var imagesArray = Array.from(images.keys());
// const images = ["./52lv.PNG", "./Capture1.PNG", "./maps.PNG"]
console.log(images.keys());
console.log('images');
console.log(images);
var constructed = [];
function constructItems(fileNames, constructed) {
fileNames.forEach(fileName => {
constructed.push({
'src': fileName.substr(1)
})
});
return constructed;
}
console.log('items ');
console.log(imagesArray);
// At build-time cache will be populated with all required modules.
var res = constructItems(imagesArray, constructed);
console.log(res);
export default {
data: function() {
return {
items: res
};
}
};
</script>
I want to read the images from the media.txt file into an array, then populate the carousel src with these. I've been trying with Webpack's require.context function, but I'm getting a module not found error.
How can I get this working?
It looks like you're trying to import a string array (JSON) into a variable. That string array should be delimited by square brackets like this:
[
"foo",
"bar"
]
require.context(dirPath, useSubDirs, filenameRegex) is not the appropriate API to use here, as that method imports multiple files from a specified directory. For instance, the code below tells Webpack to load *.png, *.jpg, and *.mp4 files from the directory named ../static/media.txt (which presumably is actually a file).
require.context('../static/media.txt', false, /\.png$|\.jpg|\.mp4/) // DON'T DO THIS
Instead, you could simply use require('path/to/file.json') to import the specified file as a JSON object/array. For example, to import src/assets/media.json (containing the array mentioned at the top), the syntax would be:
// e.g., in src/components/Foo.vue
const media = require('../assets/media.json')
console.log(media) // => [ "foo", "bar" ]
demo
You probably should install https://github.com/webpack-contrib/raw-loader#getting-started (a loader for webpack read txt files), configure it in your vue.config.js and you should be able to import like this: import txt from 'raw-loader!./file.txt'; instead using require.

How to dynamically load a Vue component after using require.context?

Currently I am loading all of my Vue components with require.context, this searches my components directory with a regex for .vue files. This works fine but I would like to load async components as well with dynamic imports.
Currently when I use require.context all files get loaded so even If I want to use a dynamic import my file is already loaded and nothing happens.
I need a way to exclude certain files from my require.context call. I cannot dynamically create a regex because this does not work with require.context.
// How I currently load my Vue components.
const components = require.context('#/components', true, /[A-Z]\w+\.vue$/);
components.keys().forEach((filePath) => {
const component = components(filePath);
const componentName = path.basename(filePath, '.vue');
// Dynamically register the component.
Vue.component(componentName, component);
});
// My component that I would like to load dynamically.
Vue.component('search-dropdown', () => import('./search/SearchDropdown'));
It seems the only way to do this is either manually declare all my components, which is a big hassle.
Or to create a static regex that skips files that have Async in their name. Which forces me to adopt a certain naming convention for components that are async. Also not ideal.
Would there be a better way to go about doing this?
const requireContext = require.context('./components', false, /.*\.vue$/)
const dynamicComponents = requireContext.keys()
.map(file =>
[file.replace(/(^.\/)|(\.vue$)/g, ''), requireContext(file)]
)
.reduce((components, [name, component]) => {
components[name] = component.default || component
return components
}, {})
Works with Vue 2.7 and Vue 3.
The lazy mode forces requireContext to return a promise.
const { defineAsyncComponent } = require('vue')
const requireContext = require.context('./yourfolder', true, /^your-regex$/, 'lazy')
module.exports = requireContext.keys().reduce((dynamicComponents, file) => {
const [, name] = file.match(/^regex-to-match-component-name$/)
const promise = requireContext(file)
dynamicComponents[name] = defineAsyncComponent(() => promise)
return dynamicComponents
}, {})
You can also use defineAsyncComponent({ loader: () => promise }) if you want to use the extra options of defineAsyncComponent.

Categories