Giter Site home page Giter Site logo

stencil-community / stencil-router Goto Github PK

View Code? Open in Web Editor NEW
187.0 21.0 55.0 1.67 MB

A simple router for Stencil apps and sites

Home Page: https://stenciljs.com/

License: MIT License

TypeScript 98.24% HTML 0.83% JavaScript 0.93%
stencil-router stencil-apps stenciljs stencil

stencil-router's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stencil-router's Issues

component-props doesn't pass down the props correctly

Hi!
PSA: I don't have any react knowledge prior to stencil but still wanna try stencil at this state of the docs.

I have this route:

<stencil-router id="router">
	<stencil-route url="/" component="my-name" router="#router" component-props={"first":"my","last":"name"} exact={true}/>
</stencil-router>

the this.componentProps is simply the string {"first":"my","last":"name"}.
If i then change route.tsx (https://github.com/ionic-team/stencil-router/blob/master/src/components/route/route.tsx#L76) to return JSON.parse(this.componentProps), it will then render the my-name example component with all its props.

(Also, the stencil-route doesn't get the component-props if the value has spaces in them.)

Am I going at it completely wrong or missing something?

stencil-router with cordova

I was trying to get stenciljs and cordova to work together. I ran into some issues and one of which was how stencil-router works with routes on cordova.

On a page in a cordova app you'll have something like:

JSON.stringify(window.location)

"{"href":"file:///android_asset/www/index.html","ancestorOrigins":{},"origin":"file://","protocol":"file:","host":"","hostname":"","port":"","pathname":"/android_asset/www/index.html","search":"","hash":""}"

If I change the route to something like:

<stencil-route url='*' component='app-home' exact={true}>

Then the app-home component just works, but that's where it stops. I was wondering/hoping it would be possible to use stencil/stencil-router with cordova applications.

Occasional Scroll Position Page Change Issue

If I refresh the same page over and over again, 50% of the time I'm at the top scroll position, and 50% of the time I'm at the bottom scroll position.

Here's a video showing the issue.
https://drive.google.com/open?id=1x0025i2quXowcTKRoIXF4GA060q-8CHa

As you can see, I am not scrolling at all, yet on page refresh, I jump from top to bottom frequently.

I believe this has to do with having a stencil element that renders many stencil elements, and those newly rendered elements also contain stencil elements. Basically, an app built with stencil.

Thanks,
Dan

Querystring

Do you plan to add support for querystring?

thx

Managing states or sub-routes

Is it possible to manage state or sub-routes ?

I come from an Angular background and the uirouter package is really great. I have some components that only need to appear in /profile/** pages but from /profile/:username and /profile/posts only a content component needs to update/change.

Is that possible with Stencil router ?

Grab rest of path

I'd like to be able to have a route match and give me the full path, for example:

<stencil-route path="/:fullPath"></stencil-route>

And then match against <stencil-route-link url="/this/whole/path"></stencil-route>

Right now it only gives me the first part of the path.

I wonder if this is a limitation of path-to-regexp.

Page-specific index.html not generated in www causing flicker when refreshed

What happened?
Imagine I have 2 routes:

<stencil-route url='/areas' component='area-list-page' />
<stencil-route url='/activities' component='activity-list-page' />                            

Somewhere in the code, I have specified <stencil-route-link> for path /areas but not /activities (it will be routed programmatically instead).

When I run npm run build, stencil will generate www/areas/index.html but not www/activities/index.html

Problem
When I deploy www to a server (eg. firebase), visiting /activities and try to refresh it, you can notice a slight flicker between the page in / and /activities. This however won't happen if I have www/activities/index.html generated in www

stencil.config.js

const sass = require('@stencil/sass')

exports.config = {
    globalStyle: 'src/global/app.css',
    plugins: [
        sass()
    ],
    outputTargets: [
        {
            type: 'www',
            serviceWorker: {
                swSrc: 'src/sw.js',
                globPatterns: [
                    '**/*.{html,js,css,scss.json,ico,png,jpg}'
                ]
            }
        }
    ]
};

exports.devServer = {
    root: 'www',
    watchGlob: '**/**'
};

Routes are not working under sub-directory website (host)

I am working on an app with a few components and trying to put it on my website under a sub-directory:

main component:

import { Component } from '@stencil/core';
import '@stencil/router';

@Component({
  tag: 'hello-stencil-main',
  styleUrl: 'hello-stencil-main.scss'
})
export class HelloStencilMain {

  render() {
    return (
      <div>
        <stencil-router root='/apps/hellostencil'>
          <stencil-route url='/' component='home' exact={true}>
          </stencil-route>
          <stencil-route url='/hello' component='hello' exact={true}>
          </stencil-route>
      </div>
    );
  }
}

stencil.config.js release config:

const sass = require('@stencil/sass');
exports.config = {
  outputTargets: [
    {
      type: 'www',
      dir: 'www',
      baseUrl: '/',
      buildDir: '',
      resourcesUrl: '/app/',
    },
    {
      type: 'www',
      dir: 'release',
      baseUrl: '/apps/hellostencil/',
      buildDir: '',
      resourcesUrl: '/apps/hellostencil/app/'
    }
  ],
  plugins: [
    sass()
  ]
};
exports.devServer = {
  root: 'www',
  watchGlob: '**/**'
};

Index.html

<!DOCTYPE html>
<html dir="ltr" lang="en">
<head>
  <meta charset="utf-8">
  <title>Hello Stencil</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0">
  <meta name="theme-color" content="#16161d">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta http-equiv="x-ua-compatible" content="IE=Edge" />
  <script src="./app.js"></script>
</head>

<body>
  <hello-stencil-main></hello-stencil-main>
</body>

</html>

package.json dependencies

"dependencies": {
   "@capacitor/cli": "^1.0.0-alpha.35",
   "@capacitor/core": "^1.0.0-alpha.35",
   "@stencil/core": "0.7.24",
   "@stencil/router": "latest",
   "@stencil/sass": "latest",
   "@types/jquery": "^3.3.1",
   "tslib": "^1.9.0"
 },
 "devDependencies": {
   "@stencil/dev-server": "latest",
   "@stencil/utils": "latest",
   "@types/jest": "^21.1.10",
   "jest": "^21.2.1",
   "typescript": "^2.8.3"
 },

After few investigations and failed tries, I figured out how to host my app under a sub-directory by adding 'root' property to and adding baseUrl to the release configs as mentioned above, this makes my home page url works('https://myhost/apps/hellostencil'), but the sub page which is under my sub-directory ('https://myhost/apps/hellostencil/hello') is not working, the component is not being rendered at all, and the stencil route tag is empty!
Also adding a <stencil-route-link url='/hello'></stencil-route-link> to my home page as anchor to go to my hello page did not make any difference.

Please help!

Note: removing 'root' tag from stencil-route and testing locally (npm start), everything works perfectly!

Routes need to be checked for matches again once a group has rendered in the dom

When using group and groupIndex to implement a wildcard route, the first load will match both the / route and the catch all route. Interestingly, after navigating to a different route, things work correctly.

  • Correct behavior would be to only match on the root route the first time a page loads
  • Can be reproduced with the latest master branch of the stencil site

Not accessible when using stencil-route-link

As stencil-route-link is not really anchor tag so by default it will not receive any focus state like a typical anchor tag.

Plus, stencil-router is not firing any custom event when the route changes. Hence, there is no way to get notified of any route change. It'd be nice if there is a way to detect route change so that certain CSS class can be applied to selected anchor tag.

I could be wrong if there had already a way to do this.

Possibility to send data on navigation

Hi, i miss this functionality and i think will be useful.

I was playing with stencil router and i get some work around to do this.

On the router link:

handleClick(e) {
    e.preventDefault();
    const router = document.querySelector(this.router);
    if (!router) {
      console.warn(
        '<stencil-route-link> wasn\'t passed an instance of the router as the "router" prop!'
      );
      return;
    }

    router.navigateTo(this.url);
  }

If you add a new Prop to receive an object, you can send that data to the other page like this:
router.navigateTo(this.url, this.data);

Then on router:

@Method()
 navigateTo(url: string, _data: any = {}) {
   window.history.pushState(null, null, url || '/');
   this.routeMatch = {
     url: url
   };
   this.stencilRouterNavigation.emit(this.routeMatch);
 }

Maybe can propagate the data like this:

    this.routeMatch = {
      url: url,
      data: data
    };

And then on route use the data on the props:
return <ChildComponent props={this.componentProps} />;

So you can send data like on ionic with data from one view to another.

Events

Has there been a discussion about supporting event hooks for the Router?

They would be kinda handy in cases like a progressbar, that changes when you change the route to indicate the loading of a page.

Events I'm thinking of:

  • onRouteChangeStart
  • onRouteChangeComplete
  • onRouteChangeError

Does anything speak against it? I'd be willing to implement it myself and create a PR. Just not sure if it fits with the existing API.

Missing pop() function in RouterHistory

dependency:
"@stencil/router": "^0.2.2"

In Stencil documentation, there's a line:
this.history.pop('/home', {});

But in actual implementation, no such function is found.

Using anchors with scrollTopOffset breaks

Using anchors to link to different sections of the same page as we do here along with scrollTopOffset breaks. When you click on the anchor tag it tries to scroll down but the scrollTopOffset logic takes over and scrolls the page back to the top.

Hash routing

Few questions:

  1. Does stencil-router listen to route that contains hash (#)?
  2. If yes, how to do scrollIntoView with hash with stencil-router?

`<stencil-route />`: lazy default matching expression

Lazy Routes

  • issue type: Question/Feature Request

Versions

├── @stencil/[email protected]
└── @stencil/[email protected]

Question

How can I declare routes, which can only match, if no other route in the current route set matches?

Current

The current behavior seems to be:
Juxtapose the corresponding components if multiple routes match.

However, I cannot find a documented way to «ungreedify» url match expressions.

Illustrative

How I would expect things to work:

<stencil-router>
    <stencil-route url="/" exact={!0} component="aurora-landing" />
    <stencil-route url="/doc" component="aurora-doc" />
    <stencil-route url="/xmp" component="aurora-xmp" />
    <stencil-route url="/bar" exact={!0} component="aurora-bar" />
    <stencil-route url="/bar/index" component="aurora-bar" />
    <stencil-route url="/bar/:path" lazy={!0} component="aurora-bar-error" />
    <stencil-route url="/:path" lazy={!0} component="aurora-error" />
</stencil-router>

How to get object through stenciljs routes

From @kchetans on June 4, 2018 11:13

I was trying to pass data through stencils routes

e.g...
this.history.push('/detail',{detail_data:docs});
when I check their interface I found
push: (path: string | LocationSegments, state?: any) => void;
so my object is state how would I access these object to /detail page
I tried
Prop() detail_data: object;
but it's not working

Copied from original issue: ionic-team/stencil#836

Nested <stencil-route> not working

Stencil version:

I'm submitting a:

[x] bug report
[ ] feature request
[ ] support request => Please do not submit support requests here, use one of these channels: https://forum.ionicframework.com/ or https://stencil-worldwide.slack.com

Current behavior:
Clicking a link pointing to a route that was just loaded from an already routed parent component makes the browser do a full postback.

Expected behavior:
Stencil app detects "lazy loaded" routes and does client side routing as with intiially loaded routes.

Steps to reproduce:
See repo:
https://github.com/bitflower/stencil-nested-routes

Warnings logged when using historyType="hash"

When using <stencil-router historyType="hash"> a warning message is logged every time you navigate to another url.

Hash history cannot push state; it is ignored
warning @ m2-about.ios.js:6766
push @ m2-about.ios.js:7200
handleClick @ stencil-route-link.js:53

There is no warning if you do not use historyType="hash".

It looks like this originates in the stencil-route-link component.

  handleClick(e: MouseEvent) {
    e.preventDefault();
    if (!this.activeRouter) {
      console.warn(
        '<stencil-route-link> wasn\'t passed an instance of the router as the "router" prop!'
      );
      return;
    }

    const history: RouterHistory = this.activeRouter.get('history');
    return history.push(this.getUrl(this.url), {});
  }

The call to history.pushlogs a warning if the second arg is not undefined.

Passing state object with history.push("...", { <state> }) does not set component properties

I have a question regarding the use of component properties when routing programmatically.
I’ve trimmed down the Ionic-PWA-Toolkit sample to following code blocks:

my-app.tsx

import '@ionic/core';
import '@stencil/core';
import { Component } from '@stencil/core';

@Component({
  tag: 'my-app',
  styleUrl: 'my-app.scss'
})
export class MyApp {

  render() {
    return (
      <ion-app>
        <main>
          <stencil-router>
            <stencil-route url='/' component='app-home' exact={true}>
            </stencil-route>

            <stencil-route url='/profile/:name' component='app-profile'>
            </stencil-route>
          </stencil-router>
        </main>
      </ion-app>
    );
  }
}

app-profile.tsx

import { Component, Prop } from '@stencil/core';
import { MatchResults } from '@stencil/router';

@Component({
  tag: 'app-profile',
  styleUrl: 'app-profile.scss'
})
export class AppProfile {

  @Prop() match: MatchResults;
  @Prop() thingOne: string;
  @Prop() thingTwo: string;

  render() {
    if (this.match && this.match.params.name) {
      return (
        <ion-page>
          <ion-header>
            <ion-toolbar color='primary'>
              <ion-title>Ionic PWA Toolkit</ion-title>
            </ion-toolbar>
          </ion-header>

          <ion-content>
            <p>
              Hello! My name is {this.match.params.name}.
              My name was passed in through a route param!
              And these are my friends, {this.thingOne} and {this.thingTwo}.
            </p>

          </ion-content>
        </ion-page>
      );
    }
  }
}

app-home.tsx

import { Component, Prop } from '@stencil/core';
import { RouterHistory } from '@stencil/router';

@Component({
  tag: 'app-home',
  styleUrl: 'app-home.scss'
})
export class AppHome {
  
  @Prop() history: RouterHistory;

  handleClick() {
    this.history.push("/profile/CatInTheHat", {
      thingOne: "Thing 1",
      thingTwo: "Thing 2"
     });
  }

  render() {
    return (
      <ion-page>
        <ion-header>
          <ion-toolbar color='primary'>
            <ion-title>Ionic PWA Toolkit</ion-title>
          </ion-toolbar>
        </ion-header>

        <ion-content>
          <p>
            Welcome to the Ionic PWA Toolkit.
          </p>

          <ion-button onClick={this.handleClick.bind(this)}>
            Profile page
          </ion-button>
        </ion-content>
      </ion-page>
    );
  }
}

In the handleClick method above, I'm attempting to programmatically route to the app-profile page and set the properties, thingOne and thingTwo, but those values do not seem to be getting set.

This is what I'm seeing (note that the URL route parameter is getting set, but not the component properties):
image

What am I missing?

Pages will not change with the latest stencil-router and @stencil/[email protected]

With the latest stencil-router and stencil/[email protected] certain pages will not be navigated too.

Repro Steps:

This is what the docs route looks like:

         <stencil-route
              url="/docs/:pageName"
              routeRender={(props: { [key: string]: any }) => {
                const map = {
                  'intro': 'intro/index.html',
                  'browser-support': 'intro/browsers.html',
                  'getting-started': 'start/index.html',
                  'my-first-component': 'basics/my-first-component.html',
                  'templating': 'basics/templating.html',
                  'decorators': 'basics/decorators.html',
                  'events': 'basics/events.html',
                  'component-lifecycle': 'basics/component-lifecycle.html',
                  'stencil-config': 'basics/stencil-config.html',
                  'forms': 'basics/forms.html',
                  'handling-arrays': 'basics/handling-arrays.html',
                  'testing': 'basics/testing.html',
                  'config': 'compiler/config.html',
                  'server-side-rendering': 'advanced/ssr/index.html',
                  'routing': 'addons/stencil-router.html',
                  'service-workers': 'advanced/service-worker/index.html',
                  'distribution': 'advanced/distribution/index.html',
                  'webpack': 'advanced/webpack/index.html',
                  'prerendering': 'advanced/pre-rendering/index.html',
                  'shadow-dom': 'advanced/shadow-dom/index.html'
                };
                return (
                  <document-component pages={[map[props.match.params.pageName]]} />
                );
              }}
            />

Router Redirect is not working

As the title says, stencil-route-redirect is not working.

Versions: core, router and dev-server are set to "next" while utils are set to "latest".

<stencil-route url="/" exact="true">
  <stencil-route-redirect url="/another-path" />
</stencil-route>
<stencil-route url="/another-path" component="app-component" />

Regards,
Bogdan

Group attribute does not result in correct rendering

Using the group attribute to render not found pages can result in unpredictable behavior.

If you are using the following router configuration:

<stencil-router>
    <stencil-route url="/" exact group="root" component="my-home" />
    <stencil-route url="/about" exact group="root" component="my-about" />
    <stencil-route url="/*" exact group="root" component="my-not-found" />
</stencil-router>

For the url /about you will sometimes get the about page but you will also sometimes get the not-found page. This is because the route matching is not done in a predictable order. The first route within the group that successfully matches "wins" so if the not-found route happens to evaluate first then it will be the one that gets rendered.

This was a real bear to track down because it only seems to happen as the application gets larger. For a simple application the routes happen to be evaluated in the order that they are defined. Once my application got larger I started to see the behavior where the order was not predictable. It may be related to timing of other async component loading.

The end result is that you can keep refreshing the page and sometimes get the page you want and sometimes get the not found page.

Routing doesn't work if deploy is in a subfolder.

From @Gafilipoie on February 15, 2018 21:46

Stencil version:

I'm submitting a:

[ x] bug report
[ ] feature request
[ ] support request => Please do not submit support requests here, use one of these channels: https://forum.ionicframework.com/ or https://stencil-worldwide.slack.com

Current behavior:
I'm running a build with npm run build command which outputs the folder www.
I'm deploying the folder to a server (xampp or heroku) and the routing doesn't work.
User visits http://localhost/www/,
then click the Alerts link,
it directs him to http://localhost/alerts/

Expected behavior:
If a user visits http://localhost/www/,
then click the Alerts link,
it should direct him to http://localhost/www/alerts/

Steps to reproduce:
http://localhost/www/ works, but if I click the Alerts link the url changes to http://localhost/alerts/ and that returns a 404 page not found.
It's like the routing doesn't work when the website is in a subfolder.

Related code:

<stencil-route-link url="/alerts" activeClass="active" exact={true}> Alerts </stencil-route-link>
<stencil-router id="router"><stencil-route  url={['/', '/alerts']} component="alerts-page" exact={true} > </stencil-route>

Other information:

Copied from original issue: ionic-team/stencil#541

Pass Aria, Role, and Tabindex values down to Anchor tag

For SEO and accessibility, these tags should be on the <a> tags if we set them as props on the <stencil-route-link>.

Note, we don't want to have those attributes on the route link and the anchor tag, so we might want to use prefixed attributes on the route link.

Something like:

<stencil-route-link exact url={url} anchor-title={myText} anchor-role="menuitem">
  {myText}
</stencil-route-link>

becomes:

<stencil-route-link class="hydrated">
  <a title="The Value of  myText" role="menuitem"  href="/the/value/of/url">
    The Value of  myText
  </a>
</stencil-route-link>

Active link class not getting removed on sub-routes

If a two routes share a similar path, the active link class will be applied to both.
This can be seen in the stencil-site repo.
Here, the active component is the demo page, but both the docs and demo link are marked as "active"

screen shot 2017-08-31 at 2 46 13 pm

Note, the landing Component's url is / and the demo component is /demo so that shared / is throwing things off. You can also see this as you navigate along the side menu links .

Error with componentWillLoad in SSR

With Express server example from docs

stencil-router:

[ ERROR ]  Runtime error detected during componentWillLoad(): stencil-router
           Cannot read property '_history' of null TypeError: Cannot read property '_history' of null at Window.get
           history [as history]

stencil-route:

[ ERROR ]  Runtime error detected during componentWillLoad(): stencil-route
           Cannot read property 'listenerList' of undefined TypeError: Cannot read property 'listenerList' of undefined
           at evalmachine.<anonymous>:3:464 at Object.subscribe (evalmachine.<anonymous>:3:550) at t.componentWillLoad
           (evalmachine.<anonymous>:2:2947) at update

componentProps in starter-app not working

<stencil-router id="app-content">
  <stencil-route url="/" component="first-name" componentProps={{ first: 'Stencil' }} exact={true} />
  <stencil-route url="/second" component="second-name" componentProps={{ first: 'Stencil2' }} />
</stencil-router>

I would expect the above to pass the value of the first prop down to <first-name/> and <second-name/> but nothing seems to happen. The prop is undefined on render.

If I use the components outside of the router they work correctly.

group required when using wildcards

This router example seems to work as expected. If the route is not /home it shows not-found-page.

<stencil-router>
  <stencil-route url="/home" component="home-page" exact={true} group="base" />
  <stencil-route url="/*" component="not-found-page" group="base" />
</stencil-router>

but if you remove the group attribute, not-found-page shows for any route, including the home page. Is this the desired behaviour?

Default/Home page always rendered with SSR

Not sure if this is related to @stencil/router or @stencil/core.

The default/home page (that handles the / path) is always being rendered with server-side rendering. This happens even if I set exact to true.

Expected behaviour:
Router should render a single route that matches the URL.

Current behaviour:
Router is rendering the default route, as well as the route that matches the URL.

To reproduce this issue, you can clone any of these repos, build the app, then run node server.js:

Trailing slash matching

My navigation uses stencil-route-link with the exact attribute.

<stencil-route-link url="/docs" exact={true}>Home</stencil-route-link>

I'm wondering if it makes sense for the above link to be considered active on both /docs and /docs/. Unless you think this is outside of scope for stencil-router, I assume we'd have to either 1) Normalize the paths or 2) consider them equal.

It looks like react-router uses a strict attribute on top of exact to determine whether to consider trailing slashes.

Defaults to bottom of the page on page change

Steps to reproduce the issue:

  1. Navigate to https://stenciljs.com/resources
  2. Scroll to the bottom
  3. Click the PWA link in the header

Observe the scroll position is not reset. You're at the bottom of the pwa page. FWIW, this behavior seems inconsistent to me. I cannot pinpoint exactly what the problem is, but I also haven't really tried 😆

Thanks,
Dan

Route guards

Ive gotten asked a few times about how to do route guards in the Stencil router. Just to be clear, by route guards i mean blocking transition to a route based on some condition. If that condition === true, navigate, if not , dont navigate. After talking to Josh it sounds like we have an API for this, but it does not have an external interface to that API. The purpose of this issue is to track adding an external interface for that API.

Why stencil router is web components library?

I wonder why this package is based on web components and not on pure js

I mean, it could nice js package that you import in your js file and use functions and config with object instead of using html tags
It's kinda confusing

Can someone explain me why web component is better than pure js plugin?

Private routes, params and componentProps

when looking at the tests you have here

https://github.com/ionic-team/stencil-router/blob/master/src/components/__tests__/test-app.tsx#L5

and using code similar to what you have provided for the PrivateRoute when I use this code, url params do not get passed down, only specific component props get passed through?

So if I have something like this...

<stencil-router>
  <PrivateRoute path="/" component="app-home" exact={true} />
  <PrivateRoute url="/profile/:name" component="app-profile" />
  <stencil-route url="/login" component="app-login" exact={true} />
</stencil-router>

i am not getting the value for :name passed through...

if I change the code to PrivateRoute to the following, then it appears to work

const PrivateRoute = ({ component, ...props}: { [key: string]: any}) => (
  <stencil-route {...props} routeRender={
    (props: { [key: string]: any}) => {
      debugger;
      console.log(props)
      console.log(component)
      if (firebaseAPI.getUser()) {
        const Component = component;
        // why do they use componentProps and not just pass thru
        // the props?
        // return <Component {...props.componentProps}></Component>;
        return <Component {...props}></Component>;
      }
      return <stencil-router-redirect url="/login"></stencil-router-redirect>
    }
  }/>
)

Error navigating: cannot read _listeners of undefined

Hi!

I'm trying to build a simple demo app with StencilJS and this router component but I'm getting an unexpected error I don't understand.

In my main App component I have the router configured like this:

<div class="main-content">
	<stencil-router>
		<stencil-route url="/" component="home-view" exact={true} />
		<stencil-route url="/podcast/:podcastId" component="podcast-view" />
	</stencil-router>
</div>

I have a home-view component with a list of items (podcasts in my case) where every one has a link to its detail page:

<div class="podcast-summary">
	<div class="box">
		<stencil-route-link url={`/podcast/${this.podcast.id}`}>
			<div class="box-icon">
				<img src={this.podcast.cover} alt={this.podcast.name} />
			</div>
			<div class="info">
				<h4 class="text-center">{this.podcast.name}</h4>
					<p>
					<span class="text-center">
						<span>Author:</span>
						<span>{this.podcast.author}</span>
					</span>
				</p>
			</div>
		</stencil-route-link>
	</div>
</div>

When I click in any link I get a bunch of errors like this one:

app.core.js:1051 Uncaught TypeError: Cannot read property '_listeners' of undefined
    at invokeDestroy (app.core.js:1051)
    at invokeDestroy (app.core.js:1058)
    at invokeDestroy (app.core.js:1058)
    at disconnectedCallback (app.core.js:1350)
    at HTMLElement.HostElementConstructor.disconnectedCallback (app.core.js:1788)
    at Object.removeChild [as $removeChild] (app.core.js:623)
    at removeVnodes (app.core.js:892)
    at updateChildren (app.core.js:964)
    at patchVNode (app.core.js:1004)
    at Object.patch [as render] (app.core.js:1038)

This is the code involved:

function invokeDestroy(vnode) {
        if (vnode) {
            var elm = vnode.elm;
            if (elm._listeners) {
                for (var key in elm._listeners) {
                    elm.removeEventListener(key, eventProxy, false);
                }
            }
            if (isDef(vnode.vchildren)) {
                for (var i = 0; i < vnode.vchildren.length; ++i) {
                    invokeDestroy(vnode.vchildren[i]);
                }
            }
        }
    }

The problem I see is that, at any point after destroying my elements in the home-view component, this function gets called with a vnode like this:

VNode {
  vattrs: undefined,
  vchildren: undefined,
  vkey: undefined,
  vtag: "slot"
}

This object has no elm attribute, so the _if (elm.listeners)... line breaks;

For further context, here is the repo of the demo app I'm building: https://github.com/PaquitoSoft/podcaster-stencil

Could you help me spot what I'm missing?

Thanks!

Passing properties with programmatically navigation

How can I pass a @Prop() between components using programmatically navigation?

e.g.
I want to pass property = { one: 'one', two: 'two' } from page-one to page-two
page-one.tsx

import { Component, Prop } from '@stencil/core';
import { RouterHistory } from '@stencil/router';

@Component({
    tag: 'page-one',
    styleUrl: 'page-one.scss'
})
export class PageOne {
    @Prop() history: RouterHistory;

    property = { one: 'one', two: 'two' };

    render() {
        return (
            <div>
                <ion-button onClick={() => this.history.push('/page-two', {})}>Page-two</ion-button>
            </div>
        );
    }
}

page-two.tsx

import { Component, Prop } from '@stencil/core';

@Component({
    tag: 'page-two',
    styleUrl: 'page-two.scss'
})
export class PageTwo {
    @Prop() property = null;

    render() {
        return (
            <div>
                <p>{JSON.stringify(this.property)}</p>
            </div>
        );
    }
}

Implement a router-switch (feature)

Hi, I have been using stencil for a few days now for my side project and it's awesome so far!. I feel like there is a need to implement a route switch that only renders one of the given routes, just like e.g. this one: React Router Switch

core 0.9.7 w/ router 0.2.0: app.core.js:2247 TypeError: Failed to resolve module specifier "@stencil/state-tunnel"

From @bitflower on May 31, 2018 18:42

Stencil version:

I'm submitting a:

[x] bug report
[ ] feature request
[ ] support request => Please do not submit support requests here, use one of these channels: https://forum.ionicframework.com/ or https://stencil-worldwide.slack.com

Current behavior:
Updated to ´0.9.7´ from 0.9.4 and to router 0.2.0 from 0.1.7 getting this in the console:
bildschirmfoto 2018-05-31 um 20 30 45

Anything I need to adopt?

This is in app-load.js:
bildschirmfoto 2018-05-31 um 20 35 10

That second import looks strange?

In the build console:

[ WARN  ]  '@stencil/state-tunnel' is imported by node_modules/@stencil/router/dist/collection/global/active-router.js,
           but could not be resolved – treating it as an external dependency

Put this on slack as well:
https://stencil-worldwide.slack.com/archives/C789G3X1R/p1527791643000262

Expected behavior:
Compiles and runs without trouble as before ;-)

Copied from original issue: ionic-team/stencil#833

Feature Request: Map match.params.* to Props

Currently, using Route parameters in a Component is clunky. Consider the following Component:

@Component({
  tag: 'my-hello'
})
export class MyHello {
  @Prop() name: string;

  render() {
    return (
      <span>Hello, {this.name}!</span>
    );
  }
}

If you want this component to used as a route, you currently have to modify it by adding a Prop to handle the route match as well as convert name to State so that the value can be updated internally via the match:

@Component({
  tag: 'my-hello'
})
export class MyHello {
  @Prop() match: any;

  @State() name: string;

  componentWillLoad() {
    if (!!this.match.params.name) {
      this.name = this.match.params.name;
    }
  }

  render() {
    return (
      <span>Hello, {this.name}!</span>
    );
  }
}

Any routable component must now:

  1. Be aware that it could be routable and accept a match.
  2. Make any route params State instead.
  3. Be responsible for optionally updating their state based on their match (and know exactly what route param identifiers they allow).

Obviously this is less than ideal. If I want my components to be truly re-usable, they shouldn't be bound to the routing mechanism.

Request

If param names in the route match Props on a component, they should be automatically mapped upon instantiating the component. This places the burden of mapping names on the consumer of the component instead of the author as well as allow easy re-use of un-modified components.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.