[7.2-7.3] Plugin development routes best practices

Hi there!

I'm developing (trying to, actually) a Kibana plugin (already opened couple of threads about it).

Here I wanted to ask you which was the best way to implement routing across the plugin pages.

Let's say in the main page of the plugin I start selecting the index pattern as a link (similar to what happens when selecting the index pattern in the machine learning plugin).

Clicking on the desired index-pattern, I'd like to go on to the next page (let's say to /category page), obviously keeping the info about the selected index pattern stored in props.
Which is the best way to accomplish that? Do I simply use Router and Route in the Main component or do I have to set something in the server/ folder?

Thank you

Hey @Fabio-sama! Client-side routing is done a number of ways within Kibana, there isn't really one right way at this point in time. You don't have to put anything in the server/ folder to accomplish this. Internally, a lot of applications use React Router. I'd highly recommend staying away from AngularJS's routing. I'd recommend looking at some internal usages of react-router-dom for inspiration and precedent.

Thank you for the reply.

I'm trying with React Router but I'm having some problems.
Following the video you linked I imported

import { BrowserRouter as Router, Route, Link } from 'react-router-dom'

Then I wanted to render a EuiInMemoryTable listing all the index-patterns and I wanted to go to the next page of the plugin at the URL #/{index-pattern} (without really seeing the hash # but the url I am at the moment, so localhost:5603/uif/app/my_plugin/my-index-pattern)

So I did something like:

return (
  <Router>
    <React.Fragment>
      <EuiInMemoryTable
        items={this.state.items}
        loading={this.state.isLoading}
        columns={[
          {
            field: 'label',
            name: this.props.table_title,
            render: (index) => (
              <span>
                <EuiIcon
                  type={this.props.icon_type}
                  size="m"
                  style={{ verticalAlign: 'text-top' }}
                />{' '}
                <EuiLink href={`/uif/app/my_plugin/${index}`} target="_self"> {/* <<<<< HOW CAN I AVOID TO WRITE THE WHOLE URL AND NOT SEE THE # EITHER ? */}
                  {index}
                </EuiLink>
              </span>
            ),
            sortable: true,
            truncateText: true,
          }
        ]}
        search={search}
        pagination={true}
        sorting={true}
      />
      <Route path='/uif/app/my_plugin/:index' component={Test}/>
    </React.Fragment>
  </Router>
);

And below I defined the component

const Test = () => (
  <div>
    <h1>Test</h1>
  </div>
)

When I click on one of the links in the table on the landing (first) page, I would expect to be redirected to a blank page with only a write Test in it.
Instead I get
image
Even though the URL is the one I would expect (http://localhost:5603/uif/app/my_plugin/kibana_sample_data_flights)

It means I'm not correctly redirecting it to the component I want to show. How can I do that?

Thanks!

I even tried using the switch (obviously importing it) like

return (
  <Router>
    <React.Fragment>
      <EuiInMemoryTable
        items={this.state.items}
        loading={this.state.isLoading}
        columns={[
          {
            field: 'label',
            name: this.props.table_title,
            render: (index) => (
              <span>
                <EuiIcon
                  type={this.props.icon_type}
                  size="m"
                  style={{ verticalAlign: 'text-top' }}
                />{' '}
                <Link to={`/uif/app/my_plugin/${index}`} target="_self">
                  {index}
                </Link>
              </span>
            ),
            sortable: true,
            truncateText: true,
          }
        ]}
        search={search}
        pagination={true}
        sorting={true}
      />
      <Switch>
        <Route path="/uif/app/my_plugin/kibana_sample_data_flights">
          <Test />
        </Route>
      </Switch>
    </React.Fragment>
  </Router>
);

And here I tried defining the functional component Test.js and importing it, rather than using const below the code.

Same 404 error.

Sorry to bother you, but can't you help me further?