2017-12-28 166 views
15

Próbuję utworzyć zdalny moduł wielokrotnego użytku. Pomysł polega na utworzeniu kontenera modelu i renderowaniu zawartości z yield i renderowaniu treści w razie potrzeby.Zdalne szyny modularne wielokrotnego użytku

Uwaga: cały kod HTML zostanie zapisany w HAML. Używam klejnotu bootstrap-modal-rails do obsługi moich modów.

Mój układ modalne pojemnik (nie częściowe):

%div(class="modal" id="mainModal ajax-modal" tabindex="-1" role="dialog"){:'aria-labelledby'=>"mainModalLabel", :'aria-hidden'=>"true"} 
    %div(class="c-modal__container") 
    %div(class="c-modal__layout modal__content") 
     = yield 

W moim application.html.haml, Mam div, który określa lokalizację modalne następująco:

-# ... 
%div(id="modal-holder") 

- unless params[:nojs] 
    = javascript_include_tag 'desktop' 

-# ... 

Tutaj jest gdzie mój problem jest od. Mam book controller, gdzie użytkownik może dodawać książki. Mam wieloetapową rejestrację, a moja akcja new musi być moim modalem. Gdy użytkownik kliknie link New book, ładuję nowy modal.

Moja New book Link:

= link_to "New book", new_book_path, class: "c-link--navbar", data: { modal: true } 

coffeescript (ponownie napisany w jQuery) dla modalnym (to kod z this article):

$(function() { 
    var modal_holder_selector, modal_selector; 
     modal_holder_selector = '#modal-holder'; 
     modal_selector = '.modal'; 
    $(document).on('click', 'a[data-modal]', function() { 
    var location; 
    location = $(this).attr('href'); 
    $.get(location, function(data) { 
     return $(modal_holder_selector).html(data).find(modal_selector).modal(); 
    }); 
    return false; 
    }); 
    return $(document).on('ajax:success', 'form[data-modal]', 

    function(event, data, status, xhr) { 
    var url; 
    url = xhr.getResponseHeader('Location'); 
    if (url) { 
     window.location = url; 
    } else { 
     $('.modal-backdrop').remove(); 
     $(modal_holder_selector).html(data).find(modal_selector).modal(); 
    } 
    return false; 
    }); 
}); 

a teraz moje new action dla yield że będzie załadowany do mojego zdalnego modala:

= form_for(@book, remote: remote, html: {role: :form}, class: "c-form") do |f| 
    -# Forms here... 
    = f.submit "Add a new book", class: "c-btn" 

Jeśli informacje użytkownika są poprawne, mój modal przekieruje użytkownika do general action w innym przypadku chcę, aby pozostawał na tej samej stronie i wyświetlał komunikat o błędzie, ale problem polegał na tym, że nie używam partial i automatycznie przekierowuje mnie do nowa strona z new action.

My books_controller.rb:

class BooksController < ApplicationController 
    respond_to :html, :json, :js 
    ... 

    def index 
    @books = current_user.books 
    end 

    def new 
    @book = current_user.books.build 
    respond_modal_with @book 
    end 

    def create 
    @book = current_user.books.build(book_params) 

    if @book.save 
     redirect_to general_book_path(@book), notice: "Saved." 
    else 
     flash.now[:notice] = "Something went wrong." 
     render :new 
    end 
    end 

    ... 
end 

Modal Odpowiadający:

class ModalResponder < ActionController::Responder 
    cattr_accessor :modal_layout 
    self.modal_layout = 'modal' 

    def render(*args) 
    options = args.extract_options! 
    if request.xhr? 
     options.merge! layout: modal_layout 
    end 
     controller.render *args, options 
    end 

    def default_render(*args) 
    render(*args) 
    end 

    def redirect_to(options) 
    if request.xhr? 
     head :ok, location: controller.url_for(options) 
    else 
     controller.redirect_to(options) 
    end 
    end 
end 

starałem się dodać coś takiego

respond_to do |format| 
    format.html 
    format.json { render json: @book } 
end 

do mojego sposobu create ale to nie działa i nadal przekierowuje ja do nowej strony. Ponadto już zadałem podobne pytanie: question. Zauważyłem, że mój kod JavaScript działa na oddzielnej stronie. O ile rozumiem, problem dotyczy mojej zdalnej strony modalnej akcji. Czy ktoś może mi pomóc, aby dowiedzieć się, jak pozostać na tej samej stronie, gdy użytkownik wprowadził błędne dane wejściowe i włączyć javascript?

+0

jeśli chcesz, aby twoja strona nie była przekierowywana. Po prostu zwróć odpowiedź ajax bez nagłówka: location – plonknimbuzz

+0

@plonknimbuzz Chcę przekierować na 'ajax: success' i pozostać na tej samej stronie, gdy' ajax: error' ... Domyślam się, że problem z moim ustawieniem ajax i kontrolera. Dziękuję bardzo za odpowiedź :) –

+0

Witaj .. Sprawdziłem twój profil github. to nie jest projekt opensource? Prawdopodobnie byłoby łatwo znaleźć rozwiązanie, debugując to ... jeśli pozwolisz mi rozwidlić twój projekt, inaczej będę mógł uzyskać głębszy wygląd. –

Odpowiedz

1

TBH to abstrakcyjne rozwiązanie, które nie jest bezpośrednio związane z pytaniem, to działa, choć (Bootstrap + JQ, na podstawie kodu produkcji)

skryptu Coffe

$.showModal = (title, body) -> 
    $("#modal").find(".modal-title").html(title) 
    $("#modal").find(".modal-body").html(body) 
    $("#modal").modal("show") 
$("#modal").find(".modal-submit").click() -> 
    $("#modal").find("form").submit() 

Html - typowy modulator ładowania początkowego:

<div id="modal" class="modal" tabindex="-1" role="dialog"> 
    <div class="modal-dialog modal-lg" role="document"> 
    <div class="modal-content"> 
     <div class="modal-header"> 
     <h5 class="modal-title"></h5> 
     <button type="button" class="close" data-dismiss="modal" aria-label="<%= t :close %>" title="<%= t :close %>"> 
      <span aria-hidden="true"></span> 
     </button> 
     </div> 
     <div class="modal-body"> 
     <p></p> 
     </div> 
     <div class="modal-footer"> 
     <button type="button" class="btn btn-danger" data-dismiss="modal"><%= t :close %></button> 
     <button type="button" class="btn btn-success modal-submit"><%= t :save %></button> 
     </div> 
    </div> 
    </div> 
</div> 

new.js.erb lub innego szyny zobaczyć

$.showModal(
    "<%= escape_javascript t :edit_comment %>", 
    "<%= escape_javascript(render 'form', :comment => @comment) %>" 
); 

link, aby otworzyć modalnego

<%= link_to t(:new), [:new, comment], :remote => true, class: "btn" %> 

Pewnie chciałby użyć własnego żądania AJAX - ten zrobi nic w przypadku serwera error/timeout

+0

Dziękuję bardzo za odpowiedź! Naprawdę doceniam twój czas. Spróbuję wdrożyć Twoje rozwiązanie. –