web-dev-qa-db-fra.com

Combinez les assistants linkTo et action dans Ember.js

J'ai besoin de combiner des assistants linkTo et action dans Ember.js. Mon code est:

{{#link-to 'index'}}<span {{action 'clear'}}>Clear</span>{{/link-to}}

Mais je voudrais faire quelque chose comme ça:

{{#link-to 'index' {{action 'clear'}} }}Clear{{/link-to}}

Et aussi:

<li>
    {{#link-to 'support'}}
        <span {{action 'myAction' 'support'}}>Support</span>
    {{/link-to}}
</li>

À:

<li>
    {{#link-to 'support' {{action 'myAction' 'support'}} }}Support{{/link-to}}
</li>

Comment puis-je atteindre cet objectif?

Solution

Vérifiez ma réponse pour Ember 2.0 compatible, OK pour la solution de référencement.

28
Daniel Kmak

Ember Link Addon Action

J'ai récemment développé cet addon pour résoudre ce problème avec le style Ember 2.0 - 2.14+ compatible (1.13 fonctionne également!) Et en tirant parti des actions/noms d'action de clôture. C'est bon pour le référencement!

Installer l'addon

ember install ember-link-action

Usage

Vous pouvez transmettre une action de fermeture en tant que invokeAction param à {{link-to}} composant:

{{#link-to 'other-route' invokeAction=(action 'testAction')}}
  Link to another route
{{/link-to}}

Vous pouvez également utiliser le nom de l'action au lieu de l'action de fermeture:

{{#link-to 'other-route' invokeAction='testAction'}}
  Link to another route
{{/link-to}}

Pour passer des paramètres à l'action, vous pouvez utiliser:

{{#link-to 'other-route' invokeAction=(action 'testAction' param1 param2)}}
  Link to another route
{{/link-to}}

Compatibilité

La suite de tests automatisés confirme que l'addon fonctionne avec les versions 1.13 et Ember 3 les plus récentes.

Il fonctionne avec une version, une version bêta et une version canari d’Ember.

Addon GitHub référentiel. Les contributions sont les bienvenues.

27
Daniel Kmak

Mise à jour: Voir le commentaire de Michael Lang ci-dessous pour Ember 1.8.1+.

Le problème avec la réponse de Myslik (ne pas utiliser link-to du tout mais utiliser plutôt un action puis un transitionToRoute) est que c'est inutile pour le référencement , les moteurs de recherche ne verront rien. 

Si vous voulez que votre lien pointe vers l'indexation, il est plus facile d'avoir un bon vieux <a href=x> dedans. Il est préférable d'utiliser link-to pour que vos URL de lien restent synchronisées avec les URL de votre itinéraire. La solution que j'utilise donne à la fois une action pour faire le travail et un link-to pratique pour indexer les pages.

Je remplace certaines fonctionnalités de Ember.LinkView:

Ember.LinkView.reopen({
  action: null,
  _invoke: function(event){
    var action = this.get('action');
    if(action) {
      // There was an action specified (in handlebars) so take custom action
      event.preventDefault(); // prevent the browser from following the link as normal
      if (this.bubbles === false) { event.stopPropagation(); }

      // trigger the action on the controller
      this.get('controller').send(action, this.get('actionParam'));
      return false; 
    }           

    // no action to take, handle the link-to normally
    return this._super(event);
  }
});

Ensuite, je peux spécifier quelle action exécuter et quoi transmettre dans le guidon:

<span {{action 'view' this}}>
  {{#link-to 'post' action='view' actionParam=this}}
    Post Title: {{title}}
  {{/link-to}}
</span>

Dans le contrôleur:

App.PostsIndexController = Ember.ArrayController.extend({
  actions: {
    view: function(post){
      this.transitionToRoute('post', post);
    }
  }
}

Ainsi, lorsque je mets en cache une copie rendue de la page et que je la sers à un bot d'indexation, celui-ci voit un lien réel avec une URL et le suit. 

(notez également que transitionTo est maintenant déconseillé en faveur de transitionToRoute)

18
Noland

Aucune de ces combinaisons ne fonctionnera dans Ember.js, mais vous n’avez pas besoin de combiner ces deux aides. Pourquoi n'utilisez-vous pas simplement Action Helper et laissez-vous en bulle au contrôleur ou à la route? Là, vous pouvez utiliser transitionToRoute dans le contrôleur ou transitionTo dans route.

Par exemple, dans le contrôleur, vous pourriez avoir un code comme celui-ci:

App.PostsController = Ember.ArrayController.extend({
    clear: function () {
        // implement your action here
        this.transitionToRoute('index');
    }
});
17
Myslik

Cela fonctionne très bien dans 1.6.0-beta.5:

<span {{action "someAction"}}>
  {{#link-to "some.route"}}
    Click Me
  {{/link-to}}
</span>

Le lien se produira et le clic sera affiché au gestionnaire d’actions. C'est documenté (même indirectement) ici .

Edit: syntaxe corrigée lors de l'ouverture de la balise link

10
neverfox

J'aime l'approche de Cereal Killer pour sa simplicité, mais malheureusement, cela pose un problème pour moi. Lorsque le navigateur navigue vers un autre itinéraire, il redémarre l'application Ember

Depuis Ember 2.6, l'approche simple suivante fait l'affaire:

<span {{action 'closeNavigationMenu'}}> {{#link-to 'home' preventDefault=false}} Go Home {{/link-to}} </span>

Cela permet d'atteindre les objectifs suivants:

  • navigue vers l'itinéraire 'à la maison'
  • l'action 'closeNavigationMenu' est invoquée
  • au survol, le navigateur affiche le lien qui sera suivi (pour le référencement et une meilleure expérience utilisateur)
  • la navigation du navigateur n'entraîne pas le redémarrage de l'application Ember
7
bargar

Ayant le même problème, j'ai trouvé cette solution simple:

{{#linkTo eng.rent class="external-button"}}<div class="internal-button" {{action "updateLangPath"}} >X</div>{{/linkTo}}

puis, gérant le bouton external et le bouton internal de la classe CSS dans la feuille de style, je me suis assuré que le "bouton interne" couvrait toute la zone "external-button"; De cette manière, il n'est pas possible de cliquer sur le bouton externe sans cliquer sur le bouton interne.

Cela fonctionne bien pour moi. espérons que cela peut aider ...

3
Cereal Killer

Voici comment j'ai résolu ce problème dans notre application de démonstration du livre O'Reilly Ember.js: https://github.com/emberjsbook .

Vous pouvez voir la source complète ici: https://github.com/emberjsbook/rocknrollcall

Dans la vue:

{{#if artistsIsChecked}}
  {{#if artists.length}}
    <h3>Artists</h3>

    <ul class="search-results artists">
      {{#each artists}}
        <li><a {{action 'viewedArtist' this.enid }}>{{name}}</a></li>
      {{/each}}
    </ul>
  {{/if}}
{{/if}}

Et le contrôleur:

App.SearchResultsController = Em.ObjectController.extend({
  actions: {
    viewedArtist: function(enid) {
      this.transitionToRoute('artist', enid);
    },
    viewedSong: function(sid) {
      this.transitionToRoute('song', sid);
    }
  },
  needs: ['artists', 'songs'],
  artistsIsChecked: true,
  songsIsChecked: true,
  artists: [],
  songs: []
});
3
jdcravens

Les balises link-to d'Ember utilisent des routes pour ouvrir de nouvelles vues. Vous pouvez ainsi exécuter la fonctionnalité que vous souhaitez insérer dans l'attribut "action" du lien dans la méthode setupController de la route cible plutôt que dans une action du contrôleur.

Voir ici dans le guide Ember: http://emberjs.com/guides/routing/setting-up-a-controller/

Cela ne fonctionne que si vous souhaitez exécuter l'action à chaque fois que vous accédez à l'itinéraire, par opposition à des liens spécifiques.

Assurez-vous d'inclure la ligne controller.set('model', model); avec tout ce que vous avez mis dedans.

0
pvans