SvelteKit routing for components - sveltekit

I have a left section containing a mini navbar (buttons: users, create, coins) and a right section containing the content I want to display (display coins section when coins button is clicked, ...)
However currently, the routing I want to achieve is not what I want at the moment.
When for example, the users button is clicked, I want the routing/url to be shown as settings/users, rather than just settings, settings/create for the create button and settings/coins for the coins button.
The following is the code:
settings/+page.svelte
<script>
import { page } from '$app/stores'
import Create from './create/+page.svelte'
import Users from './users/+page.svelte'
import Coins from "./coins/+page.svelte"
export let data
let loading = false
let currentSetting = 'create'
$: currentSetting = $page.url.hash?.substring(1) || 'create';
</script>
<div class="flex mt-5 h-full">
<!-- Left section -->
<div class="flex flex-col items-center gap-4 w-44">
Create
Users
Coins
</div>
<div class="divider divider-horizontal"></div>
<!-- Right section -->
<div class="flex-1">
{#if currentSetting==='create'}
<Create categories={data?.categories}/>
{:else if currentSetting==='users'}
<Users bind:loading={loading} users={data.allUsers}/>
{:else if currentSetting==='coins'}
<Coins bind:loading={loading} users={data.allUsers}/>
{/if}
</div>
</div>
where coins, create and users are all components in settings/coins/+page.svelte, settings/create/+page.svelte and settings/users/+page.svelte respectively.
When a button is clicked, currentSetting changes such that the display changes to the correct display (users button clicked, displays users settings.
I have tried using a pseudo route for each component, but I do not want to use it as it cannot have its own +page.server.js.
Thus, changing the link of a anchor tag is needed.
I was thinking of using slug, but I'm unsure of how to actually use it.

I believe you are confusing pages and components.
In SvelteKit, pages are placed under /src/routes/ in a hierarchy that mirrors your desired URL paths to access each page. SvelteKit will then infer the routing from that /src/routes/ directory structure. This is where you will define +page.svelte, +page.js, etc. files for page declarations, +layout.svelte etc. files for layouts, +server.js files for endpoints, etc.
You do not need to import pages in order to link to them, you simply use the standard HTML ... tag with the correct URL to reach the page you want linked to. For instance, a page declared as /src/routes/settings/users/+page.svelte will be, by convention, accessible on your site at yoursite.com/settings/users and can be linked to with Users.
You can read about SvelteKit routing in detail here.
In addition to pages, you can also create components, which are like reusable building blocks for your pages. These are typically placed under /src/lib/ and have names like MyForm.svelte. These components will have to be imported in your page files before you can use them there.
You can find a typical SvelteKit project structure here.
Complementary information: using layouts
Layouts are part of the /src/routes tree and help define common structural elements shared by several pages.
Layouts usually apply to all the pages that are located below them in the /src/routes/ directory hierarchy, although there are special mechanisms available to escape individual page files from using layout(s) that would normally apply to them.
Layouts can be nested. In your particular use case, for instance, you would want to locate your side navigation in /src/routes/settings/+layout.svelte. This is what it that file would look like:
// /src/routes/settings/+layout.svelte
<script>
export let data; // from the layout's load() function, see further below
$: current = data.route.id
</script>
<div class="flex mt-5 h-full">
<!-- Left section -->
<div class="flex flex-col items-center gap-4 w-44">
Create
Users
Coins
</div>
<div class="divider divider-horizontal"></div>
<!-- Right section goes here -->
<div class="flex-1">
<slot></slot>
</div>
</div>
And the accompanying /src/routes/settings/+layout.js:
// /src/routes/settings/+layout.js
export function load({ route }) {
return { route };
}
The above load function will simply get the name of the route from the incoming request and pass it on to the layout (and its child pages). You need this in order to properly set the btn-active class in your side navigation for the currently active page.
With the layout defined above, any pages declared under /src/routes/settings/ will apply this layout and be loaded into the <slot></slot> declared in the layout.
You can read more about SvelteKit layouts here.
Note that all of this is really the A-B-C of SvelteKit. I urge you to go back to the docs to get a solid grasp of a SvelteKit project structure and a thorough understanding of its routing/page structure conventions.

Related

SvelteKit loading indicator when a page load time threshold is exceeded

I am using SvelteKit for a website that is mainly server-side rendered pages. The client-side navigation on SvelteKit works beautifully and is super snappy. However, sometimes, when the backend server is called in the route load() function, the response is not instant and maybe several seconds because of the database long-tail latency.
What would be the best way to create a loading indicator that is only displayed if the loading time is not instant (sub 200ms)? I am aware of the generic navigating pattern, but I specifically hope to create a loading indicator that is not triggered unless the page load is not instant.
Sveltekit has a store variable called "navigating" which literally indicates if the client is in-between loading pages. From the Sveltekit docs:
navigating is a readable store. When navigating starts, its value is { from, to }, where from and to both mirror the page store value. When
navigating finishes, its value reverts to null.
Note, that if your page is pre-rendered, it should be "instant" and thus not show a loading indicator. If not, this "navigating" variable will be not null for as long as it takes for your content to be fetched and/or rendered. If you wanted to, you could make the "Spinner" component show nothing...until after 200ms (using a setTimout timer)...which it sounds like you do want.
Here's a sample implementation from a wrapper component I have used in the past (pardon the tailwindcss syntax...I copied and pasted it). You can customize this idea in __layout.svelte or wrap components or entire "pages" with this {#if $navigating} logic:
<script>
// USE THIS:
import { navigating } from '$app/stores'
// Example spinner/loading component is visible (when $navigating != null):
import Spinner from '$lib/design/Spinner.svelte'
...
</script>
<main class="py-4">
<div class="pagePaddingMain flex-col">
{#if title}
<h1 class="text-4xl text-center text-cText pb-4 sm:text-5xl">{title}</h1>
{/if}
{#if $navigating} <!-- LOOK HERE -->
<div class="m-8">
<Spinner />
<h1 class="ext-3xl text-center text-cText">Fetching {title}...</h1>
</div>
{:else}
<slot />
{/if}
</div>
</main>
That's it. Good luck!

Optimize page load of multiple pages

I've a multiple page site. I created a single component enclosing all the texts/para/images. I've refered this component to all the multiple pages. I used a class name to hide/show the content to the respective pages via css. Problem is that the page load is slow. Since all contents are hidden using css they are still loaded making my site slow. Any help on this is much appreciated. Thanks
There are multiple things you can check.
Check the internet connectivity, I hope you have good internet connectivity to load the
page.
As you say there are multiple page with single component, check if you can move those into sub-component.
I am not sure how you're hiding those components use css property display:none if those are light weight.
you can use something like this:
<style type="text/css">
.hidden { display:none; }
</style>
render: function() {
return (
<div className={this.props.shouldHide ? 'hidden' : ''}>
This will be hidden if you set <tt>props.shouldHide</tt>
to something truthy.
</div>
);
}
// or in more modern JS and stateless react
const Example = props => <div className={props.shouldHide}/>Hello</div>
source

Semantic-UI-React Footer

I've been learning ReactJS for the past couple of days and have been trying to build a website using semantic-ui-react in ReactJS. I understand there are components that one can use now but I am stuck on what to do in a scenario such as the creation of a footer... typically, in my raw HTML, I would have the semantic.min.css file included and at the bottom:
<div class="ui inverted pink vertical footer segment">
<div class="ui center aligned container">
<h4 class="ui inverted header">© Copyright 2017 | All rights reserved | Blahhh</h4>
<i class="facebook square icon big"></i>
<i class="twitter square icon big"></i>
<i class="linkedin square icon big"></i>
</div>
</div>
Now I want to translate this into semantic-ui-react. Footer is a class not a component in react by default so there's no component for it... Which I assume means I have to make my own component and basically write the code above. My problem now is that I don't know how to make it render as if I was using regular old semantic.min.css. I read somewhere to download the css file and include it, but one, I don't know where to (MyCustomFooterComponent or index.html), and in doing that, am I not increasing by load times on my website. Would this mean that everywhere there's a footer, just for one small section of custom code, the entire CSS file is going to be loaded?
Also, after building, would there be a double-import scenario from my addition of the Semantic CSS and semantic-ui-react's CSS?
Sorry for the long question but I'm new to this and I like to find out what I can before making a terrible mistake.
If you are using react-semantic-ui then you already include 'the old semantic-ui.min.css' already. See here.
Hence, create a component and put those code in render(), change 'class' to 'className' and then use it.

Polymer display content based on URL

I'm trying to create a custom element for reuse. What I have is data consisting of three attributes that will be displayed on it's respective page, depending on the link you click.
I'm using the Polymer Starter Kit. Basically, I want to have a page of information that changes depending on what the URL is. I have a list of programs on a page with links to their respective pages. So far I have this:
In my index.html, I have a section that looks like this:
<section data-route="programs">
<paper-material elevation="1">
<h1>Programs</h1>
<a href$="{{baseUrl}}programs/firstprogram">Program 1</a></br>
<a href$="{{baseUrl}}programs/secondprogram">Program 2</a></br>
<a href$="{{baseUrl}}programs/thirdprogram">Program 3</a></br>
</paper-material>
</section>
Then I have a custom element, program-info, that looks like this
<dom-module id="program-info">
<template>
<h2 class="page-title">{{program.name}}</h2>
<p>{{program.price}}</p>
<p>{{program.description}}</p>
</template>
<script>
(function() {
'use strict';
Polymer({
is: 'program-info'
});
})();
</script>
</dom-module>
Based on the program that was clicked, I want to grab data and use it in my custom element (name, price, description). I've thought about putting it in an array since there are only seven programs, but I don't know understand how to grab the right item in the array based on the URL.
Any thoughts?
If you are indeed using PSK, take a look at the section/page user-info in app/index.html. It displays information about a user based the name that was grabbed from the URL.
Of course you should also take a look at the routing configuration in app/elements/routing.html to figure out how the name is grabbed from the URL and set to the params variable.
Then you should add/modify your programs route to suit your needs.
Edit:
You can see a similar approach in this sample app : The data is fetch when the route changes and is then set to an article property in the scope of the blog-app element. In this element, said article property is itself bound to the similarly named property of the "page element" article-detail that is in charge of displaying the article's content that was previously fetched over the network.

Best approach to change background image in AngularJs at runtime

I want to create generic feature that allows me to change background image of any section. After going through options provided I found these two approaches. Want to choose best approach to change image because on single page I want multiple times change background facility. It will be available to four to five sections.
Approach
Using Directive check this stack overflow link.
Also there is another approach of angular scope variables that we can updates at runtime.
<div ng-style="{'background-image': 'url(/images/' + backgroundImageUrl + ')'}"></div>
Required Usage ( With respect of Directive )
<body>
<section backgroundImage url="{{backgroundImageUrl1}}">
...
</section>
<section backgroundImage url="{{backgroundImageUrl2}}">
...
</section>
<section backgroundImage url="{{backgroundImageUrl3}}">
...
</section>
<section backgroundImage url="{{backgroundImageUrl4}}">
...
</section>
</body>
As shown above I am going to update background-image attribute for each section. If these property is set inside CSS file, it will reduce time to load images i.e. If we directly add inline css styling in HTML, all images will loaded on DOM load. It will make extra request to server to get images and load them in DOM. I wanted to follow strategy that will reduce loading time in my SPA(Single Page Application).
I think going with <div ng-style="{'background-image': 'url(/images/' + backgroundImageUrl + ')'}"></div> should be more effective.
You dont introduce another layer of complexity, directives create scopes, which are watched and digested, also directives must be compiled in the begining.
Using symple ng-style together with some specific url from controllers property shoudl only do request for that particular active image. Because of that i think it should be the optimal solution.

Resources