Material-ui: [MenuItem] Links innerhalb von Menüpunkten

Erstellt am 6. Jan. 2015  ·  43Kommentare  ·  Quelle: mui-org/material-ui

Hallo, ich habe mir die aktuelle Implementierung von Menüpunkten angesehen und festgestellt, dass es keinen eigentlichen Link gibt (dh HTML <a> Tag). So gibt es beispielsweise auch in der Navigationsleiste keinen eigentlichen Link und Übergänge zu anderen Seiten werden über onclick-Ereignisse gesteuert.

Ich denke, es wäre eine Verbesserung, Links zu haben, insbesondere wenn man serverseitig gerenderte Seiten bedenkt.

Halten Sie das für sinnvoll oder haben Sie konkrete Gründe, diese Richtung nicht einzuschlagen?

v0.x

Hilfreichster Kommentar

Verwenden Sie die containerElement Requisite!

sehen:
http://stackoverflow.com/questions/32106513/material-ui-menu-using-routes/34507786#34507786

<MenuItem
  containerElement={<Link to="/profile" />}
  primaryText="Profile"
  leftIcon={
    <FontIcon className="material-icons">people</FontIcon>
  } />

Alle 43 Kommentare

Darüber frage ich mich auch. Ich verwende serverseitiges Rendering in meiner Anwendung. Dies ist etwas, das Sie sich ansehen sollten.

Die Verwendung von Ankerelementen mit href Attributen würde auch die Zugänglichkeit verbessern und es den Benutzern ermöglichen, das Browserverhalten zu verwenden, an das sie gewöhnt sind (zB ⌘-Klick, um einen neuen Tab zu öffnen).

+1

+1

+1

+1

+1

+1

+1

@ecesena denkst du, dass dies immer noch ein Problem mit der neuen Komponente MenuItem ? Siehe hier . Die MenuItem s können von <a>..</a> , nicht wahr?

Dies ist möglich mit dem, was @shaurya947 vorgeschlagen hat.

Ich versuche, MenuItems in meinem LeftNav wie folgt zu verwenden:

        let menuItems = (
            <div>
                <MenuItem primaryText="Doors"           leftIcon={<FontIcon className="material-icons" color={GlobalStyles.default.activeColor}>home</FontIcon>} /></a>
                <MenuItem primaryText="Load"           leftIcon={<FontIcon className="material-icons" color={GlobalStyles.default.activeColor}>home</FontIcon>} />
                <MenuItem primaryText="Notes"           leftIcon={<FontIcon className="material-icons" color={GlobalStyles.default.activeColor}>home</FontIcon>} />
                <MenuItem primaryText="Alerts"          leftIcon={<FontIcon className="material-icons" color={GlobalStyles.default.activeColor}>home</FontIcon>} />
                <MenuItem primaryText="Admin"           leftIcon={<FontIcon className="material-icons" color={GlobalStyles.default.activeColor}>home</FontIcon>} />
            </div>
        );

        return (
            <LeftNav
                ref="leftNav"
                docked={false}
                onChange={this._onLeftNavChange}
            >
                {menuItems}
            </LeftNav>
        )

Wenn ein <a> um ein <MenuItem> Tag gewickelt wird, wird eine Warnung ausgegeben validateDOMNesting(...): <a> cannot appear as a descendant of <a>. See MainLayout > a > ... > MenuItem > ListItem > EnhancedButton > a"

Wenn Sie eine React-Inspektion der Ausgabe durchführen, erhalten Sie Folgendes.

<a href="/">
    <MenuItem..>
        <ListItem..>
            <div>
                <EnhancedButton..>
                    <a>
                        <TouchRipple ..>
                    </a>
                </EnhancedButton>
            </div>
        </ListItem>
    </MenuItem>
</a>

was verschachtelte <a> Elemente anstößig ist.

<MenuItems> generiert <a> Elemente innerhalb der Button Deklaration. Welche Requisite wird von MenuItem , um das href-Attribut innerhalb des generierten <EnhancedButton> füllen?

Wenn Sie ein MenuItem-Objekt als Requisite für LeftNav verwenden, funktioniert die Verknüpfung, aber ich konnte nicht herausfinden, wie man auf diese Weise linke / rechte Symbole hinzufügt.

dh:

let menuItems = [
         { route: '/load_areas/'+ this.state.area + '/doors', text: 'Doors' },
         { route: '/load_areas/'+ this.state.area + '/trailer_loads', text: 'Load' },
         { route: 'notes', text: 'Notes' },
         { route: 'alerts', text: 'Alerts' },
         { route: 'admin', text: 'Admin' }
         ];

<LeftNav
                ref="leftNav"
                docked={false}
                menuItems={menuItems}
                onChange={this._onLeftNavChange}
            />

Dies ist eine separate Ausgabe, bitte öffnen Sie eine, damit wir sie beschriften und zu Meilensteinen hinzufügen können, tnx :grin:

Verwenden Sie die containerElement Requisite!

sehen:
http://stackoverflow.com/questions/32106513/material-ui-menu-using-routes/34507786#34507786

<MenuItem
  containerElement={<Link to="/profile" />}
  primaryText="Profile"
  leftIcon={
    <FontIcon className="material-icons">people</FontIcon>
  } />

Jetzt ist die Requisite linkButton von EnhancedButton veraltet. LinkButton ist nicht mehr erforderlich, wenn die Eigenschaft href bereitgestellt wird. Es wird mit v0.16.0 entfernt.

Beispielsweise:

<MenuItem primaryText="Primary Text" href="/your/link" />

href lädt die Seite neu. Wie wäre es, wenn ich den React-Router verwenden möchte?

@cezarneaga versuche href="#/your/link"

<MenuItem
  containerElement={<Link to="/profile" />}
.../>

Dokumentation erwähnt, dass Sie auch linkButton eingeben müssen. Wenn Sie dies entfernen, funktioniert es ohne Fehler.

@DaxChen Ich habe Ihre Stackoverflow-aktualisierte Antwort für Dezember 2016 gesehen (extrem aktuell haha) und ich habe mich gefragt, ob Sie wissen, ob dies für ein MenuItem in einer Schublade funktioniert? Ich versuche folgendes und konnte Link nicht mit dem MenuItem zum Laufen bringen, da containerElement nichts zu tun scheint.

<Drawer
  docked={false}
  width={300}
  onRequestChange={this.closeDrawer}
  open={this.state.open}>
  <AppBar title="Title"
 />
  <MenuItem primaryText="home" containerElement={<Link to="/home" />} />
</Drawer>

containerElement funktioniert, ist aber nicht dokumentiert, daher denke ich, dass dieser Thread vorerst als offizielle Dokumentation dienen muss. Danke!

Hallo @Faolain !

Sorry für die späte Antwort...
Ich habe versucht, Sie mit create-react-app in einer sauberen App zu
Vielleicht haben Sie react-router anders konfiguriert oder ist die Version anders?

Wie auch immer, hier ist ein Beispiel-Repo und die Live-Demo hier .

Wenn Sie die Ursache Ihres Problems immer noch nicht finden können, können Sie ein Beispiel-Repository zur Reproduktion bereitstellen?

Keine der oben genannten Lösungen funktionierte auf Safari und iOS. Also hier ist, was ich als Workaround für react-router

          <MenuItem
            onTouchTap={() => {
              this._yourMethod()
              browserHistory.push('/howItWorks')
            }}
            primaryText="Menu Link"
          />

@janzenz funktioniert dieses Beispiel hier nicht in deinem Browser?

Ich habe es in Safari unter macOS und Safari unter iOS ausprobiert und sie alle funktionieren. Funktioniert das bei dir nicht?

Obwohl Ihre Problemumgehung funktioniert, kann sie zu schlechter SEO führen und Sie verlieren einige native Verhalten wie Link-Vorschau und Option-Klick zum Öffnen in neuem Tab.

@DaxChen danke für die Einblicke. Ich bin mir nicht sicher, ob mein Problem mit Ihrem ersten Link zusammenhängt. Ich habe bereits den zweiten versucht, aber sobald ich eine onTouchTap Requisite hinzufüge, funktioniert die <Link /> nicht mehr.

@janzenz Ich habe in meinem vorherigen Beispiel onTouchTap prop hinzugefügt und es funktioniert immer noch.
Weiß nicht ob deine Einstellung irgendwo anders ist oder so... 😢
Sie können den aktualisierten Code überprüfen und sehen, ob er für Sie funktioniert?

@DaxChen Wie ich sehe, verwendest du material-ui in der Version ~0.16.0 . Haben Sie die neuesten ~0.17.0 ausprobiert und sehen, ob das immer noch kein Problem ist?

@janzenz Ich habe eine ältere Version verwendet, gerade auf das neueste 0.17.4 aktualisiert und es funktioniert immer noch!

Touché! Dann wahrscheinlich mein Setup. Danke für die Bestätigung, dass @DaxChen ich auf diesen Thread zurückkomme, wenn ich das eigentliche Problem gefunden habe.

@DaxChen , ich habe das Beispiel versucht, das du mir gegeben hast, aber es schlägt fehl

Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in. Check the render method of `EnhancedButton`.
    at invariant (invariant.js:44)
    at ReactCompositeComponentWrapper.instantiateReactComponent [as _instantiateReactComponent] (instantiateReactComponent.js:74)
    at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:367)
    at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactDOMComponent.mountChildren (ReactMultiChild.js:238)
    at ReactDOMComponent._createInitialChildren (ReactDOMComponent.js:697)
    at ReactDOMComponent.mountComponent (ReactDOMComponent.js:516)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
    at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
    at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactDOMComponent.mountChildren (ReactMultiChild.js:238)
    at ReactDOMComponent._createInitialChildren (ReactDOMComponent.js:697)
    at ReactDOMComponent.mountComponent (ReactDOMComponent.js:516)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
    at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactDOMComponent.mountChildren (ReactMultiChild.js:238)
    at ReactDOMComponent._createInitialChildren (ReactDOMComponent.js:697)
    at ReactDOMComponent.mountComponent (ReactDOMComponent.js:516)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
    at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactDOMComponent.mountChildren (ReactMultiChild.js:238)
    at ReactDOMComponent._createInitialChildren (ReactDOMComponent.js:697)
    at ReactDOMComponent.mountComponent (ReactDOMComponent.js:516)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
    at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
    at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
    at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
    at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
    at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
    at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
    at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
    at Object.mountComponent (ReactReconciler.js:46)
    at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
    at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
    at Object.mountComponent (ReactReconciler.js:46)
    at mountComponentIntoNode (ReactMount.js:104)
    at ReactReconcileTransaction.perform (Transaction.js:140)
    at batchedMountComponentIntoNode (ReactMount.js:126)
    at ReactDefaultBatchingStrategyTransaction.perform (Transaction.js:140)
    at Object.batchedUpdates (ReactDefaultBatchingStrategy.js:62)
    at Object.batchedUpdates (ReactUpdates.js:97)
    at Object._renderNewRootComponent (ReactMount.js:320)
    at Object._renderSubtreeIntoContainer (ReactMount.js:401)
    at Object.render (ReactMount.js:422)
    at Object.<anonymous> (index.js:36)
    at __webpack_require__ (bootstrap e3e2367…:555)
    at fn (bootstrap e3e2367…:86)
    at Object.<anonymous> (bootstrap e3e2367…:578)
    at __webpack_require__ (bootstrap e3e2367…:555)
    at bootstrap e3e2367…:578
    at bootstrap e3e2367…:578

Mein Code ist verfügbar unter https://github.com/hhimanshu/spicyveggie/tree/cards ( cards Zweigstelle)

Ich bin mir nicht sicher was anders ist, aber es funktioniert einfach nicht

@janzenz
Ich habe auch browserHistory.push('/howItWorks') ausprobiert und import browserHistory from 'react-router-dom' importiert, aber undefuned .

@Oduig ,
Ich habe es mit #/your/link versucht, aber es bringt mich nirgendwo hin
Ich habe /your/link versucht, aber es lädt die Seite neu und ich verliere Drawer von Material-UI

Keines dieser Dinge hat bei mir funktioniert. Mein Code ist verfügbar unter https://github.com/hhimanshu/spicyveggie/tree/cards ( cards Branch), spezifischer Commit ist https://github.com/hhimanshu/spicyveggie/commit/844b7b7cddf9102995cd2680a783df3b6ef48537 , Könnte jemand bitte helfen?

@hhimanshu ändere diese Zeile in

import { Link } from 'react-router-dom'

mehr Infos zu MDN

@DaxChen , danke. Das war es. Wenn meine Seite jedoch nicht mit {<Link to="/menu"/>} geladen wird, wird die gesamte Seite geladen und mein Drawer ist weg.

screen shot 2017-04-24 at 1 54 23 pm

@hhimanshu Das liegt daran, dass Sie nur die Menu Komponente in Ihrer \menu Route verwendet haben , also wird App nicht gerendert.

Verschachteln Sie Ihre Menu und Summary in App oder einigen Layoutkomponenten und übergeben Sie die entsprechenden Kinder.

Die gerenderte Komponentenhierarchie und deren Zustände können Sie mit React-devtools überprüfen!

Dies hat nichts mit material-ui zu tun, bitte lesen Sie mehr in den Tutorials/Docs von React-Router.

+1

Problemumgehungen für Links HANDLED & NOT HANDLED by React Router.


Wenn der Ziellink von React Router verarbeitet wird

MenuItemLink.js

import React from 'react';
import { MenuItem } from 'material-ui/Menu';
import { Route } from 'react-router-dom';

class MenuItemLink extends React.Component {
  render() {
    const {
      to, also,
      ...rest
    } = this.props;

    return (
      <Route
        render={({ history, location }) => (
          <MenuItem
            onClick={() => {
              history.push(to);
              if (typeof also === 'function') {
                also();
              }
            }}
            {...rest}
          />
        )}
      />
    );
  }
}
MenuItemLink.muiName = 'MenuItem';
export default MenuItemLink;

Beispielcode:

import MenuItemLink from './MenuItemLink';
<Menu ... >
        <MenuItemLink to="/users"
          also={this.handleRequestClose}>Users</MenuItemLink>
</Menu>

Wenn der Ziellink NICHT von React Router verarbeitet wird, dh: Anfrage wird an einen API-Server oder was auch immer weitergeleitet

onClick-Funktion:

    function facebookLoginRedirect () {
      if (window) window.location.href = "/api/auth/facebook"
      return true;
    }

Beispielcode:

<MenuItem onClick={ facebookLoginRedirect }>Login with Facebook</MenuItem>

Ich komme, um dies zu ergänzen, falls noch jemand darüber gestolpert ist.

Auf v3.4 können Sie dies wie folgt erreichen:

import { Link } from 'react-router-dom';
import MenuItem from '@material-ui/core/MenuItem';

...

<MenuItem component={Link} to="/your-path">...</MenuItem>

Die einzige Lösung, die für mich funktionierte, ohne das Menü-Layout zu beschädigen, war:
```javascript


Benachrichtigungen



Profil


Die einzige Lösung, die für mich funktionierte, ohne das Menü-Layout zu beschädigen, war:

<MenuList>
  <Link to='/your-path' style={{ textDecoration: 'none' }}>
    <MenuItem>
      Notifications
     </MenuItem>
  </Link>
  <Link to='/your-path' style={{ textDecoration: 'none' }}>
    <MenuItem>
      Profile
     </MenuItem>
  </Link>
</MenuList>

@eladlevy Dies würde in einem HTML mit schlechter Semantik enden.

<ul>
  <a><li/></a>
  <a><li/></a>
</ul>

Lassen Sie dies hier, falls es jemandem hilft (mit v3.9.0). Ich brauchte ein <Select> , um als Menü von react-router-dom <Link> s zu fungieren. Jeder Link entsprach einer Spracheinstellung, sodass das Dropdown-Menü den Wert der aktuellen Sprache aus dem Abfrageparameter anzeigen würde.

<Select value={currentLanguage}>
  {languages.map(language => (
    <ListItem
      button
      component={btnProps => (
        <Link
          to={ `/things?lang=${ language }` }
          {...btnProps as any}
        />
      )}
      value={language}
      key={language}
    >
      {language}
    </ListItem>
  ))}
</Select>

Dies war die sauberste Lösung, die ich finden konnte, die ein minimales TypeScript-Casting erforderte und die visuelle Darstellung im Einklang mit der Material-Benutzeroberfläche beibehalten musste.

@goyney hat die Lösung, danke

Ich komme, um dies zu ergänzen, falls noch jemand darüber gestolpert ist.

Auf v3.4 können Sie dies wie folgt erreichen:

import { Link } from 'react-router-dom';
import MenuItem from '@material-ui/core/MenuItem';

...

<MenuItem component={Link} to="/your-path">...</MenuItem>

Funktionierende und saubere Lösung, danke ❤️

Für externe Links sollten Sie component="a" , aber auch MenuItem in <li> :

<MenuList>
    <li>
        <MenuItem
            component="a"
            href="https://google.com"
            target="_blank"
        >Google</MenuItem>
    </li>
</MenuList>

Dadurch wird folgender HTML-Code generiert:

<ul class="MuiList-root MuiList-padding" role="menu" tabindex="-1">
    <li>
        <a class="[...]" tabindex="-1" aria-disabled="false" role="menuitem" href="https://google.com" target="_blank">Google</a>
    </li>
</ul>

Angenommen, ich habe ein Popup-Menü und verwende

import { Link } from 'react-router-dom';
importiere MenuItem von '@material-ui/core/MenuItem';

\\

Der Link ruft die /your-path-Seite auf. Wie würde man das Popup-Menü schließen?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen