SvelteKit: how do I do slug-based dynamic routing? - javascript

I am a newbie on Svelte and in coding in general. I'd prefer to learn SvelteKit (Svelte#Next) rather than sapper since that seems to be where Svelte is heading.
For my personal project, I need to support dynamic routing based on url slugs. How do I do that in SvelteKit? For example, if I have /blog directory and need to pull content based on its "id", how would I do that?
The part that I am having difficulty with is accessing the URL slug parameter.
Thanks in advance.

you can create a file with the [brackets] : touch src/routes/blog/[slug].svelte
And paste the following code
<script>
import { page } from '$app/stores';
</script>
{$page.params.slug}
Then navigate to your app http://localhost:3000/blog/123
You should see your result
In order to create content for the http://localhost:3000/blog page, you can modify src/routes/blog/index.svelte

As of SvelteKit 1.0 the path should be a directory in brackets, e.g. for /blog/<slug> you will add the following:
src/routes/blog/[slug]
|_ +page.js
|_ +page.svelte
Then in src/routes/blog/[slug]/+page.js you can add something like
export const load = ({ params }) => {
return {
slug: params.slug
}
}
which will return it as a data property to +page.svelte, so you can write something like:
<script>
export let data;
</script>
<h1>{data.slug}</h1>
Reference: https://kit.svelte.dev/docs/routing

Caveat - the info in my reply probably may not be valid as SvelteKit matures, but from experiments I have done thus far, this works:
Parameter based routing is similar to the sveltejs/sapper-template. You should learn how Sapper does it first. Lets say I have a route blog with a single param slug (/blog/page-1 & /blog/page-2)
Create a route component in routes/blog named [slug].svelte
Copy the content from the sveltejs/sapper-template example.
Rename the preload function to load with a single parameter such as ctx
Alter the return object to append your slug property to props
export async function load(ctx) {
let slug = ctx.page.params.slug
return { props: { slug }}
}
If your blog has multiple params for the slug (/blog/2021/01/29/this-is-a-slug), you can remove [slug].svelte and create a file name [...data].svelte and change your load method to:
export async function load(ctx) {
let [year, month, day, slug] = ctx.page.params.data;
return { props: { data: { year, month, day, slug }}}
}
Don't forget to define your data property as an object. Here's a typescript example:
<script lang="ts">
export let data: { slug: string, year: number, month: number, day: number };
</script>
From there use the values as {data.slug}, etc
Happy hacking

I also had some issues with the Typescript import so here is a complete Typescript example.
Structure:
src/routes/coins/[coin_name]
|_ +page.ts
|_ +page.svelte
+page.ts:
import type { PageLoad } from './$types';
export const load: PageLoad = ({ params }) => {
return {
name: params.coin_name
}
}
export interface CoinPage{
name: string
}
+page.svelte and the use of the data:
<script lang="ts">
import type { CoinPage } from "./+page";
export let data:CoinPage;
</script>
<h1>{data.name}</h1>

Related

Dynamically import all images from a folder in Astro

I am working with Astro. The project uses quite a few images, and I want to simplify the way I currently add new images. My routes are like:
example.com/pictures/[collection]
( "[" and "]" stands for a dynamic route )
Allowing for example:
example.com/pictures/mixed-tecnique
example.com/pictures/graphite
example.com/pictures/acrylic
In the file pages/pictures/[collection].astro I want to do the following (or something similar):
---
import * as collections from "public/img/collections"
const { collection } = Astro.props
---
{collections[collection].map(imgSrc => <img src={imgSrc} />)}
So now, to have a new Collection route, I just have to create a new folder and drop the images there.
Is there any way to do something to reach the same result? Thanks in advance!!
There are a bunch of different ways to implement a feature like this but here is a simple example making use of the fast-glob library
public
pictures
mixed-technique
example.png
example.png
example.png
graphite
example.png
example.png
example.png
arcylic
example.png
example.png
example.png
// src/pages/pictures/[collection].astro
---
import fg from 'fast-glob';
export async function getStaticPaths() {
// get all collection folder paths: 'public/pictures/[collection]'
const collections: string[] = fg.sync('public/pictures/*', { onlyDirectories: true })
// Create a new route for every collection
return collections.map(collection => {
// Create Route
return {
params: {
// Return folder name of collection as dynamic parameter [collection]
collection: collection.split('/').pop()
},
props: {
// Return array of all image srcs in collection as prop 'images'
images: fg.sync(`${collection}/**/*.{png,jpg}`).map(img => img.replace('public/', '/'))
}
}
})
}
export interface Props {
images: string[];
}
const { collection } = Astro.params
const { images } = Astro.props
---
<html lang="en">
<head>
<!-- ... -->
</head>
<body>
{ images.map(img => <img src={img}/>) }
</body>
</html>
Note: I used fast-glob instead of Astro.glob or import.meta.glob() because it can take a variable as an argument (makes this logic easier/more dynamic) and because it only returns an array of file/folder paths instead of also attempting to return file content

Render docx in React js

I would like to properly render a docx file in React JS with the correct formatting, as it would appear in Word or a similar service. Currently, when displaying the text, all formatting is removed and appears as plain text. I obtain the file from the server, and process it, by:
const url = "http://localhost:8080/files/aboutme.docx";
axios.get(url, {
responseType: 'arraybuffer',
}).then(response => {
var doc = new Docxtemplater(new PizZip(response.data), {
delimiters: {
start: 'ran',
end: 'ran'
}
});
var text = doc.getFullText();
setAboutMe(text);
})
I am using the Docxtemplater and PizZip libraries.
Docxtemplater is
a library to generate docx/pptx documents from a docx/pptx template
If you need to render a docx file I think you should use react-doc-viewer. Then you could write something like:
import DocViewer from "react-doc-viewer";
function App() {
const doc = [{ uri: "http://localhost:8080/files/aboutme.docx" }];
return <DocViewer documents={doc} />;
}

nuxt.js get default head in vue.js component

I am trying to get the head object that is configured by nuxt.config.js in a vue layout. In order to show the same title in an app bar as the page title.
I know that you can alter the page title with the head function in a vue component. But is it also possible to retrieve this information somehow?
<script>
export default {
data () {
return {
title: head.titleTemplate // possible?
}
},
head () {
// here it is possible to change it but how about getting it?
}
}
</script>
Another approach could be to get some data out of an page in the nuxt.config.js. But I think this is not how the hierarchy is structured.
Thanks for you help I am just starting to use javascript to code a website :)
(If I understand you correctly) You can use the changed callback to keep track of the latest meta info used (and thus the title).
Example:
head() {
return {
changed: (info) => {
this.title = info.title;
console.log(info, info.title);
},
};
},
data() {
return {
title: '',
};
},
In nuxt.config.js before export I have setted variable with a string of the title.
Then added it to the head section and create a new env section:
https://nuxtjs.org/api/configuration-env/
const title = `Site title`
export default {
head: {
title
},
env: {
title
}
}
This how I'm getting the title in any Vue component:
export default {
computed: {
title () {
return process.env.title
}
},
}
This helps you to keep your original title in process.env.title, even if you will want to change head.title dynamically.
Did anyone found a better solution maybe? :)

NextJS import images in MDX

I tried a official NextJS MDX-Blog example.
https://github.com/mdx-js/mdx/tree/master/examples/next
But what I'm not able to figure out is how do I setup the NextJS config to load images via webpack?
import img from "./image.jpg"
## Hallo Blogwelt
![My own Image]({img})
You can also use the /public directory to hold your images. For example, if you add an image at /public/image.jpg, you can reference the image in your blog post like this:
![Alt Text](/image.jpg)
Edit: https://nextjs.org/docs/basic-features/image-optimization#local-images
Imagine your next.config.js as something to append to an existing webpack.config behind the scenes. You won't have direct access to the webpack but you can extend it.
So in order to load images you'll need an appropriate image loader.
I found next-images easiest to use:
const withImages = require('next-images')
module.exports = withImages({
webpack(config, options) {
return config
}
})
then you can import:
import Img from "./image.jpg"
Hey thanks for the tip!
It's been a while since June and a gave it another try today and now it's working like expected from me.
I took the MDX/Next Example
Edited the next.config.js like so:
const withPlugins = require('next-compose-plugins');
const images = require('remark-images');
const emoji = require('remark-emoji');
const optimizedImages = require('next-optimized-images');
const withMDX = require('#zeit/next-mdx')({
extension: /\.mdx?$/,
options: {
mdPlugins: [images, emoji]
}
});
module.exports = withPlugins([
[
withMDX,
{
pageExtensions: ['js', 'jsx', 'md', 'mdx']
}
],
[optimizedImages]
]);
Now it works exactly like expected and in a Markdown file within the pages folder I'm able to do something like this:
import Layout from '../../components/Layout'
import Image from './catimage.jpg'
# Hey guys this is the heading of my post!
<img src={Image} alt="Image of a cat" />
Sorry I'm late, but with Next v11 you can directly import images.
That being said, you can add custom loaders for Webpack to modify your mdx files and use a custom component to process the image. e.g.:
// save this somewhere such as mdxLoader and
// add it to your webpack configuration
const replaceAll = require("string.prototype.replaceall");
module.exports = function (content, map, meta) {
return replaceAll(
map
content,
/\!\[(.*)\]\((.+)\)/g,
`<NextImage alt="$1" src={require('$2').default} />`
);
};
and process it:
// and reference this in your MDX provider
const components = {
NextImage: (props: any) => {
return <Image alt={props.alt || "Image"} {...props} />;
},
};
Now you can use markdown flavored images in your posts!
![my image](./image.png)
Include the ./ relative prefix, however.
I'm building a Next.js blog with MDX-Bundler. It allows you to use a remark plugin called remark-mdx-images which converts markdown flavored images into JSX images.
Below is an example configuration to get it to work
const {code} = await bundleMDX(source, {
cwd: '/posts/directory/on/disk',
xdmOptions: options => {
options.remarkPlugins = [...(options.remarkPlugins ?? []), remarkMdxImages]
return options
},
esbuildOptions: options => {
options.outdir = '/public/directory/on/disk/img'
options.loader = {
...options.loader,
'.jpg': 'file'
}
options.publicPath = '/img/'
options.write = true
return options
}
})
You can check out the following resources for detailed explanation on how to do it.
Images with MDX-Bundler
How I built the new notjust.dev platform with NextJS
If you installed the #next/mdx package you can use the <Image /> component Next.js provides:
// pages/cute-cat.mdx
import Image from "next/image";
import cuteCat from "./cute-cat.jpg";
# Cute cat
This is a picture of a cute cat
<Image src={cuteCat} />

Loading only single language JSON file in Angular multilaguage

I am working on ionic application. I want to add multi-language support for the same using language .json files. So I googled it and found few examples for loading files using "angular static file loader plugin", but it loads all the language files at once.
My question is, can we load user selected language file only to avoid extra time for loading other language files. Can anybody please let me know how can I achieve it ?? or loading all files at a time is better approach ?? or is there any better implementation I can do ??
Thank you.
My question is, can we load user selected language file only to avoid extra time for loading other language files.
Yes.
Can anybody please let me know how can I achieve it ?? or loading all files at a time is better approach ?? or is there any better implementation I can do ??
Use angular-translate and angular-translate-loader-url
in your app.config()
$translateProvider.useUrlLoader('/translate');
$translateProvider.preferredLanguage('en_US');
This will be an equivalent of request /translate?lang=en_US to get the specific language (default) when your app initial.
Later when you want to change to another language:
// Example in one of your controller
$translate.use('fr_FR');
This will trigger a request /translate?lang=fr_FR to fetch another translation file
I have created JSON files of language as "en.json" in my project.. and I want to use that file.. so is it possible by using above code?
For JSON files, as mentioned in your question angular-translate-loader-static-files Will do the trick (I am not sure why you have all file loaded in once, because it supposed to be lazy loading)
$translateProvider.useStaticFilesLoader({
prefix: '',
suffix: '.json'
});
$translateProvider.preferredLanguage('en');
This will load en.json.
To lazy load another translation file.
$translate.uses('fr');
This will load fr.json
Best way to change language Globally is to use pipes and send the language parameter as an argument.
This would automatically change the Language across the components where the language pipe is utilized.
The following example can be used to supple multiple language at a time and can be used to change Language dynamically on a single click
// for example: **language.pipe.ts**
import { Pipe, PipeTransform, OnInit, OnChanges } from '#angular/core';
import { LanguageService } from '../services/language.service';
#Pipe({
name: 'language'
})
export class LanguagePipe implements PipeTransform {
constructor(
public lang: LanguageService
) { }
transform(value: string, args?: any): any {
return this.lang.getLang(value);
}
}
// **language.service.ts**
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
#Injectable()
export class LanguageService {
selectedLanguage = 'ch';
segmentsNames: any = {};
constantSegmentNames: any = {};
language = {
undefined: { 'en': '', 'ch': '' },
null: { 'en': '', 'ch': '' },
'': { 'en': '', 'ch': '' },
'hello': { 'en': 'Hello', 'ch': '你好' },
'world': { 'en': 'World', 'ch': '世界' }
};
constructor(private _http: HttpClient) { }
getLang(value: string, args?: any): any {
if (this.language[value]) {
return this.language[value][this.selectedLanguage];
}
return value;
}
/**
* #function that is used to toggle the selected language among 'en' and 'ch'
*/
changeLanguage() {
if (this.selectedLanguage === 'en') {
this.selectedLanguage = 'ch';
} else {
this.selectedLanguage = 'en';
}
}
}
// **Use Language Pipe in HTML AS**
<strong>{{'hello' | language:lang.selectedLanguage}}{{'world' | language:lang.selectedLanguage}}</strong>
PS: Don't forget to import the pipe & service in all the components where you want to use this functionality
Conslusion: you can write your own logic to fetch the appropriate Language.json file based on user selected language and use it in the service above mentioned

Categories

Resources