IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Ruby on Rails Discussion :

Ajouter des éléments x lors d'ajout d'un élément y


Sujet :

Ruby on Rails

  1. #1
    Membre régulier Avatar de Miles Raymond
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Avril 2005
    Messages : 189
    Points : 83
    Points
    83
    Par défaut Ajouter des éléments x lors d'ajout d'un élément y
    Bonjour,

    J'ai une table services et une table pieces. La deux tables sont liées en has_many through. De ce côté là, tout va pour le mieux dans le meilleur des mondes. Ensuite, à la création d'un nouveau service, l'utilisateur peut sélectionner des pièces depuis la table éponyme et les ajouter au service en cours de création.

    J'ai suivis, en partie, le tutoriel de Ryan Bates sur les formes complexes dans lequel il permet à l'utilisateur d'ajouter de nouvelles tâches à un projet. Mais son exemple est plus facile, car chaque nouvelle tâche à ajouter est unique et créée à la volée, alors que je suis obligé d'aller retrouver ces informations dans une autre table.

    J'aimerais connaître votre avis sur la meilleure façon de faire. A noter que j'ai envie d'effectuer ce processus en ajax. En fait, j'ai réussi à créer l'interface d'ajout et de suppression d'éléments en javascript depuis ma base, mais ensuite, quand j'envoie mon forme, les éléments crées dynamiquement ne sont pas envoyés. J'ai tenter une alternative en copiant en partie le processus expliquer par Bates, seulement je n'arrive pas à envoyer à mon partial uniquement les éléments sélectionnés par l'utilisateur. Il faudrait que je puisse créer une collection des éléments sélectionnés et que j'envoie celle-ci à mon partial, ensuite, mon partial fait un fields_for et affiche chaque élément sélectionné de ma collection.

    Ca serait un bon début, mais comment créer cette collection.. mystère ! Sinon qu'en pensez-vous ?

    Merci beaucoup !

  2. #2
    Membre éprouvé

    Profil pro
    Inscrit en
    Mai 2005
    Messages
    657
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 657
    Points : 910
    Points
    910
    Par défaut
    seulement je n'arrive pas à envoyer à mon partial uniquement les éléments sélectionnés par l'utilisateur.
    Avant ton partial, il y a un controller. A mon avis c'est a lui de gérer ça.
    Toute la documentation Ruby on Rails : gotapi.com/rubyrails
    Mes articles :
    > HAML : langage de template pour Ruby on Rails

  3. #3
    Membre régulier Avatar de Miles Raymond
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Avril 2005
    Messages : 189
    Points : 83
    Points
    83
    Par défaut
    Citation Envoyé par Taum Voir le message
    seulement je n'arrive pas à envoyer à mon partial uniquement les éléments sélectionnés par l'utilisateur.
    Avant ton partial, il y a un controller. A mon avis c'est a lui de gérer ça.
    Comment ? Je fais un form_remote_tag contenant toutes mes pièces et lorsque j'envoie mon formulaire à ma page "new" (ma page actuelle donc) j'actualise les données des pièces et je les affiches avec un partial ? Mon soucis c'est qu'il faut que je travail uniquement en js sur des données non "écrites" ! Puisque l'utilisateur peut ajouter 50 pièces et finalement, faire annuler sans que ça n'aie la moindre incidence nulle part.

    Donc imaginons un :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <% form_remote_tag :update => "pieces", :url => { :action => "new"} do %>
       <% for p in @pieces %>
       <%=check_box_tag "p_check_<% p.id.to_s %>" %><%=h p.description %>
       <% end %>
    <% end %>
    Dans mon new. J'affiche ça avec le plugin redbox (c'est juste une div hidden sur ma page, rien d'exceptionnel) et quand je clique sur ajouter, j'envois donc toutes ces infos à mon controller.

    Et après, je fais quoi ? Je n'ajoute pas ces enregistrements dans ma base, donc depuis ici je récupère et affiche mes données comment exactement ?

    Du coup je suis un peu lourdé.

  4. #4
    Membre régulier Avatar de Miles Raymond
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Avril 2005
    Messages : 189
    Points : 83
    Points
    83
    Par défaut
    Personne n'a d'idée ?
    Je vais essayer de réexpliquer un peu le processus. L'utilisateur clique sur "ajouter un service", dans cette fenêtre, il entre les informations principale du service puis, en cliquant sur "Ajouter des pièces" il peut insérer directement les pièces dont il a besoin pour ce service. Le lien affiche, grâce au plugin redbox, une div cachée présente sur ma page qui contient toutes les pièces. Ce div s'affiche comme une fenêtre modale, ensuite l'utilisateur entre des quantités pour les pièces qui l'intéresse, ou plus simplement les cochent, et en cliquant sur "Ajouter les pièces" elles viennent s'ajouter grâce à ajax dans ma fenêtre d'ajout de service.
    Il est ensuite possible de supprimer des pièces, de modifier leur quantité et d'en ajouter d'autres. Mais chacune de ces opérations n'altérant pas ma base de donnée.

    Et au final, quand je clique sur "Ajouter le service" ruby recevra en paramètres l'id des x pièces et leur quantité pour les lier à mon service.

    Mes deux bases sont correctement configurées en through.

    Voilà, connaissez-vous un exemple, un tutorial ou avez-vous déjà procéder à ce type d'opération ? Comment feriez-vous ?

    --- Mes tests
    J'ai réaliser une fonction me permettant d'ajouter et de supprimer des pièces intégralement en javascript/prototype. Ce n'est pas très compliqué. Seulement ces paramètres ne sont pas envoyés à Ruby. Pire, lorsque j'affiche la source de ma page après avoir ajouter x pièces, ma div contenant les pièces est vide ! Donc Ruby ne reçoit aucune pièce à ajouter. Et je ne peux pas dynamiquement depuis javascript, écrire du ruby genre "$(pieces).insert('<% fields_for machinchose %>')".

    Ensuite j'ai essayer d'écrire un link_to_function dans ma fenêtre modale qui donnerait quelque chose comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <%=link_to_function "Ajouter" do |page|
    	page.select('#piece').each do |v|
                 [je regarde lorsque j'ai une quantité ou que l'élément est sélectionné et je génère un nouveau @piece pour chaque ligne]
                 page.insert_html :bottom, :pieces, :partial => 'piece', :object => @pieces
      	end
    	page << "RedBox.close()"
    end %>

  5. #5
    Membre du Club
    Inscrit en
    Octobre 2007
    Messages
    68
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 68
    Points : 61
    Points
    61
    Par défaut
    Bonjour,

    Une question :
    Quand tu clic sur "Ajouter les pièces" et que tes pieces viennent s'ajouter dans ta fenêtre d'ajout de service :
    Est ce que tu raffraichi entièrement ton formulaire d'ajout de service ?

    Ce que je veux dire, c'est que si c'est uniquement un raffraichissement local dans ton formulaire, les nouvelles informations ne seront pas envoyées par ton submit Ajouter le service,
    car lorsque ce lien a été créé dans ta page, les pieces n'étaient pas encore créées.

    Peut être tu pourrais envoyer tes fichiers vues et controlleurs, qu'on comprenne mieux ce que tu fais.

    Sinon, une solution peut-être plus simple pour éviter de garder toutes les modifications en mémoire, serait d'avoir une table temporaire dans laquelle tu enregistre toutes les modifications au fur et à mesure que des pieces sont ajoutées/supprimées.
    Et lorsque l'utilisateur clic sur Ajouter le service, tu reportes les info de cette table temporaire dans ta table principale, puis tu supprime les enregistrements de ta table temporaire.

  6. #6
    Membre régulier Avatar de Miles Raymond
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Avril 2005
    Messages : 189
    Points : 83
    Points
    83
    Par défaut
    Merci de ta réponse bab_dev. Peut-être que je me complique un peu la vie, mais jusque là j'ai fait pas mal d'avance. J'ai mis un remote_form_tag autour de ma liste de pièces et je l'envoi à ma page.

    Dans mon controller je vérifie si le params[:piece] existe (c'est ce que j'envoi par Ajax) et après, je créer dynamiquement un tableau de pieces auxquelles je donne id et quantite et j'affiche ce tableau à partir d'un partial. Ensuite quand je fais "Ajouter" je vois bien toutes mes pièces dans les paramètres (merci Firebug).

    MAIS il y a un kouak là au milieu, disons que je n'ai pas encore réussi à créer mon tableau dynamique (je l'ai remplis avec des dummy value pour le teste). Je suis toujours un peu paumé dans le hash de mon form.

    Voilà ma form d'envoi des pièces :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <% form_remote_tag :url => { :action => "new", :id => @machine.id }, :html => { :id => "add_pieces_form"} do %>
    	  <% for p in @pieces %>
    		<p>
    			<%=hidden_field_tag "piece["+p.id.to_s+"]", p.id, :name => "piece[id]",  :class => "id_piece" %> <%=label_tag :piece_description, p.description, :id => "piece_description_"+ p.id.to_s, :value => p.description, :name => "piece[description]" %> <%=text_field_tag "quantite_piece["+ p.id.to_s+"]", nil, :name => "piece[quantite]", :class => "quantite_piece" %>
    		</p>
    	  <% end %>
    	  <%=submit_tag "Ajouter", :name => nil, :onclick => "RedBox.close()" %> ou <%= link_to_close_redbox "Annuler" %>
    	<% end %>
    Et une fois envoyé, voilà un exemple de paramètres envoyés :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    authenticity_token   ad36705794c43af89c4222f240b872d6f7b96775
    piece[id]            121
    piece[id]            122
    piece[quantite]      12
    piece[quantite]
    Et là j'ai bien du mal à travailler avec mon hash. En fait il ne regroupe pas mes piece[id] et mes piece[quantite] dans un seul élément [piece]. Tout est mélangé et j'ai bien du mal à récupérer les valeurs dont j'ai besoin, avez-vous des idées ? Comment nommer mes text_field de manière à parcourir facilement mon "params" ?

    Note : Désolé bab_dev de ne pas répondre directement à tes questions, mais j'ai tellement modifié mon code que j'aurais voulu avoir votre opinion sur l'état actuel de mon travail.

    Si vous êtes curieux, voici la fonction de mon controller qui récupère mes paramètres :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    if params[:piece]
        	render :update do |page|
        		@selected_pieces = []
        		params[:piece].each do |f|
        			@piece = { Hash dans laquelle je créer ma pièce en fonction des attributs de "f" }
        			@selected_pieces << @piece
        		end
        		page.insert_html :top, :pieces, :partial => "piece", :collection => @selected_pieces
        	end
        end

  7. #7
    Membre éprouvé

    Profil pro
    Inscrit en
    Mai 2005
    Messages
    657
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 657
    Points : 910
    Points
    910
    Par défaut
    Il me semble que si tu appelles tes champs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    piece[][id]
    piece[][quantite]
    piece[][id]
    piece[][quantite]
    tu peux ensuite récupérer un tableau de hash :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [{"id" => 121, "quantite" => 12}, {"id" => 122, "quantite" => 3}]
    De mémoire... c'est à tester

    Autrement une maniere plus "bidouille" est de donner des noms differents à tes champs, exemple: quantite_121, quantite_122, etc.
    Toute la documentation Ruby on Rails : gotapi.com/rubyrails
    Mes articles :
    > HAML : langage de template pour Ruby on Rails

  8. #8
    Membre du Club
    Inscrit en
    Octobre 2007
    Messages
    68
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 68
    Points : 61
    Points
    61
    Par défaut
    Désolée de pas répondre plus tôt j'étais occupée ailleurs...

    Un problème que je vois dans ton code, c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    <%=hidden_field_tag "piece["+p.id.to_s+"]", p.id, :name => "piece[id]",  :class => "id_piece" %>
    <%=label_tag :piece_description, p.description, :id => "piece_description_"+ p.id.to_s, :value => p.description, :name => "piece[description]" %> 
    <%=text_field_tag "quantite_piece["+ p.id.to_s+"]", nil, :name => "piece[quantite]", :class => "quantite_piece" %>
    Le nom de ton champ et que tu retrouveras dans params est dans :name,
    donc pour toutes tes pièces tu as le même nom.
    Le plus simple à mon avis est de différencier les noms de tes champs comme l'a proposé Taum.

    Ce que j'aurais fait, c'est de mettre dans tes champs text_field_tag :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
      :name => "piece_" + p.id.to_s + "[quantite]"
      :name => "piece_" + p.id.to_s + "[description]"

    Tu réccupère alors dans params :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    piece_121 => { id => 121, quantite => ..., description => ...}, piece_122 => { id => 122, quantite => ..., description => ...},

    Tu peux même certainement supprimer ton hidden field contenant l'id, car tu peux le réccupérer dans ton controlleur depuis le texte de piece_122

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
      params.keys.each do |pkey|
         if pkey.slice(0..5) == "piece_"
            p_id = pkey.slice(6..pkey.size).to_i
            puts "ID=" + p_id.to_s
     
            # les valeurs correspondantes sont dans params[pkey] :
            puts p(params[pkey])
         end
      end
     
    # ID=121
    # {"quantite"=>"quantite_de_p_121", "description"=>"..."}
    # ID=122
    # {"quantite"=>"quantite_de_p_122", "description"=>"..."}
    J'ai testé vite fait... j'espère que je t'ai pas mis trop d'erreurs!

Discussions similaires

  1. Réponses: 0
    Dernier message: 21/10/2014, 17h41
  2. Ajouter des élément a un tableau
    Par Death83 dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 31/07/2007, 14h23
  3. [Shell] Ajouter des éléments au poste de travail
    Par Feeder_Fan dans le forum Framework .NET
    Réponses: 2
    Dernier message: 04/12/2005, 04h07
  4. [Client mail] Problème lors de l'ajout des comptes
    Par Leobaillard dans le forum Web & réseau
    Réponses: 9
    Dernier message: 19/11/2005, 17h12
  5. Ajouter des éléments à ListBox
    Par priest69 dans le forum Access
    Réponses: 5
    Dernier message: 20/09/2005, 14h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo