2016-03-08 2 views
0

Я новичок рельсов и у меня есть это веб-приложение, которое позволяет пользователям создавать новые задания на печать с помощью Rails 4Rails: Как добавить объект через bootstrap modal?

приложения/модели/job.erb

class Job < ActiveRecord::Base 
    belongs_to :job_type 
end 

приложения/модели/job_type.erb

class Job < ActiveRecord::Base 
    has_many :jobs 
end 

в новой форме создания рабочих мест пользователь должен выбрать тип задания для своей новой работы из списка, который я сумел заставить его бросить следующий код.

приложение/просмотров/работы/_form.html.erb

<div class="row"> 
    <div class="col-md-6 col-md-offset-3"> 
    <%= form_for(@job) do |f| %> 

     ..... 

     <div class="field"> 
     <%= f.label :job_type_id %><br> 
     <%= f.collection_select :job_type_id, JobType.all,:id,:name %> 
     </div> 
     <!-- Modal --> 
     <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> 
     <div class="modal-dialog" role="document"> 
      <div class="modal-content"> 
      <div class="modal-header"> 
       <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> 
       <h4 class="modal-title" id="myModalLabel">Modal title</h4> 
      </div> 
      <div class="modal-body"> 
       ... 
      </div> 
      <div class="modal-footer"> 

      </div> 
      </div> 
     </div> 
     </div> 

    <% end %> 

    </div> 
</div> 

И через какой-то кофе сценарий мне удалось добавить «Другой» вариант в меню Типы заданий, который выстреливает модальное #myModal добавить новый JobType к базе данных, если его не существует ...

приложения/активы/JavaScript/jobs.coffee

$('#job_job_type_id').append("<option>Other</option>") 
$('#job_job_type_id').change -> 
    jobType = $('#job_job_type_id :selected').text() 
    if jobType == "Other" 
    $('#myModal').modal('show') 
    else 
    $('#myModal').modal('hide') 

кодекс работает хорошо и запускает самозагрузки модальности. Но это я не знаю, что делать дальше?

Я пробовал много кода и рассмотрел множество вопросов, но мне не удалось сделать этот модальный способ добавить новый тип JobType и обновить список, я полагал, что это требует некоторой модификации контроллеров и фантазии AJAX кода за пределами моего знания ...

у меня есть некоторые вопросы здесь

1) То, что я должен поместить в код модальной, чтобы иметь возможность добавить новую JobType в базу данных, затем вернуться в новый Форма создания заданий и вновь созданный тип заданного типа

2) Какие контроллеры необходимо изменить? и как? Какой код AJAX нужен?

3) Как изменить фактор работы _form? Могу ли я поместить модальный код в новый Partial? Если да, то как это реализовать?

Надеюсь, вы можете мне помочь, я изо всех сил пытался решить эту проблему в течение нескольких дней. Спасибо

ответ

0

Ok, во-первых, чтобы ответить на ваши вопросы:

1) То, что я должен поместить в код модальной, чтобы иметь возможность добавить новую JobType в базу данных, затем вернуться к новой форме создания рабочих мест и new created JobType selected

Ваш модаль добавит форму, по существу, форму, которую вы, вероятно, имеете под app/views/job_types/_form.html.erb, но у нее будет кнопка, которая будет отправлять через AJAX вместо формы submit.

2) Какие контроллеры необходимо изменить? и как? Какой код AJAX нужен?

Вам нужно будет добавить метод к job_types_controller, который может обрабатывать вышеупомянутый вызов AJAX.Это необходимо:

  • Сохраните новый тип задания
  • возвращает статус успеха и вновь созданный объект к абоненту.

3) Как изменить фактор работы _form? Могу ли я поместить модальный код в новый Partial? Если да, то как это реализовать?

У вас должен быть метод, который при вызове добавляет новую возможность в список. Вы можете поставить модальный код в частичном или нет, до вас; это решение не имеет никакого отношения к функциональности всего этого.

Итак, что вам нужно сделать здесь:

SERVER (ДИСПЕТЧЕР):

1) Создание метода в config/routes.rb, который может обрабатывать вызов AJAX.

resources :job_types do 
    post :append, on: :collection 
end 

Это добавляет настраиваемый маршрут ресурсов. Поскольку мы добавляем его таким образом, мы автоматически получаем функцию URLHelper append_job_types_path.

2) Внесите этот метод в controllers/job_types_controller.rb, чтобы сохранить новый тип JobType и вернуть его (и, самое главное, его идентификатор) вызывающему.

def append 
    job_type = JobType.new 
    job_type.name = params[:job_type_name] 
    if job_type.save 
    render :status => 201, :json => { id: job_type.id, name: job_type.name } 
    else 
    err_msg = job_type.errors.empty?? 'Save failed' : job_type.errors.full_messages.join('; ') 
    render :status => 400, :json => { message: err_msg } 
    end 
end 

Если сэкономить хорошо, идентификатор и имя нового объекта будут возвращены в качестве JSON вызывающему. Если нет, мы возвращаем сообщение об ошибке и любые сообщения проверки.

Теперь мы готовы использовать эти методы ...

КЛИЕНТ (VIEW):

1) Создайте кнопку, которая может запустить модальный

Вы уже сделали это!

2) Добавить форму в модальном, который может представлять тип задания

<%= form_tag(append_job_types_path) do %> 
    Enter Job Name:<br/> 
    <input type="text" name="new_job_type_name" id="new_job_type_name" /> 
    <br/> 
    <input type="button" value="Submit" id="append_job_type_submit" /> 
<% end %> 

И действительно, не нужно быть в форме, поскольку мы отправки через AJAX, но вы будете вероятно, получите некоторую помощь по стилю, используя ее. Однако атрибуты id здесь важны для следующих шагов. Обратите внимание, что я использую form_tag здесь, а не form_for. Это потому, что я не буду прикреплять что-либо к форме (или представлять ее в этом отношении).

3) На отправить (эр, по нажатию кнопки), отправить имя, введенное пользователем, чтобы новый метод AJAX

Здесь мы будем использовать Ненавязчивый JavaScript, чтобы зацепить слушателя метод для кнопки отправки. Вы можете поместить этот код в нижней части окна, или вы можете переместить его в CoffeeScript:

javascript: 
    $("#append_job_type_submit").click(function() { 
    var name = $("#new_job_type_name").val(); 
    //TODO: validation on the name, ensure it's not blank, etc 
    $.ajax({ 
     url: '/job_types/append', 
     method: 'POST', 
     data: {job_type_name: name}, 
     success: function(data) { 
     //TODO: Handle success 
     }, 
     error: function(err) { 
     //TODO: Handle error 
     } 
    }); 
    }); 

Здесь мы посылаем вызов AJAX к методу сервера, передавая имя введенного пользователем.Обратите внимание, что я оставил место для простой проверки, которую вы можете сделать до отправки

4) После ответа добавьте новую опцию в список.

Это продолжается функция сверху:

javascript: 
    $("#append_job_type_submit").click(function() { 
    var name = $("#new_job_type_name").val(); 
    //TODO: validation on the name, ensure it's not blank, etc 
    $.ajax({ 
     url: '/job_types/append', 
     method: 'POST', 
     data: {job_type_name: name}, 
     success: function(data) { 
     var sel = $("#job_type_id"); 
     sel.append('<option value="' + data.id + '">' + data.name + '</option>'); 
     $("#myModal").modal('hide'); 
     alert("New job type " + data.name + " created."); 
     //TODO: probably be nice to auto-select this option; I'll leave that exercise to the alert reader 
     }, 
     error: function(err) { 
     alert(err.responseJSON.message); 
     } 
    }); 
    }); 

Теперь пользователь может выбрать опцию из выберите поле, и новый вариант был сохранен в базе данных (независимо от того, или не создать ли они новая работа).

Отказ от ответственности: Я не тестировал этот код и даже не проверял, скомпилирован ли он. Но это должно сработать, и независимо от того, это шаблон, за которым вы хотите следовать, поэтому, если ничего другого, по крайней мере, у вас есть направление сейчас.

Теперь, все, что сказал, я бы порекомендовал другой подход без AJAX, который я предложил, поскольку он отсекает большинство этих шагов, но это только я. Не стесняйтесь принимать любой ответ, который поможет вам выполнить ВАШУ задачу так, как вы этого хотите.

Примечание: Я решил опубликовать это в дополнение к aldrien Ответим как у меня есть несколько различий, которые я нашел достаточно, чтобы оправдать его:

  • Успех и ответ отказ должен вернуть успех/провал код статуса. Если он всегда возвращает успех, это немного вводит в заблуждение. Я думаю, что коды статуса являются важной частью любого проекта REST, даже такого маленького, как этот.
  • Я бы рекомендовал использовать только match маршруты в качестве крайней меры. Находчивые маршруты чище и понятнее, и они также дают вам больше возможностей. Кроме того, мне нравится маршрут под /job_types, а не только плавающий в корне.
  • Кроме того, более стандартная вещь должна быть запросом POST вместо GET; мы все-таки создаем новый объект.
  • Ошибка: метод append должен давать data.id для значения параметра, а не data.title (который должен быть data.name в соответствии с исходным кодом). В противном случае значение не будет идентификатором, и попытка сохранения завершится с ошибкой.
+0

!, Большое вам спасибо, Ваш ответ был ясен. Вы прошли меня, шаг за шагом, объясняя все. И он работал отлично, как я хотел. кроме одного: '<% = form_tag (append_job_type_path) do%>' Он продолжал давать мне ошибку 'undefined local variable or method 'append_job_type_path'', но когда я изменил ее на:' <% = form_tag (append_job_type_path) сделать %> 'Это сработало просто отлично, Который" И я смущен, чтобы сказать "решение, которое я не совсем понимаю. Но в любом случае Спасибо –

+0

Спасибо, я обновил это в ответ для потомков. Если вы хотите какие-либо разъяснения на что-либо, не стесняйтесь комментировать и спрашивать! – GoGoCarl

0

Во-первых, установите кнопку или форму в вашем модальном для запуска функции отправки.

Во-вторых, настроить/проверить маршруты/URL-адрес, который будет использоваться для метода AJAX.

А также настройка функции контроллера для сохранения нового типа задания.

пример Контроллер:

def create 
    job_type = JobType.new 
    job_type.title = params[:job_type] 
    if job_type.save 
    render :json => job_type 
    else 
    render :json => "some error here." 
    end 
end 

Наконец, сделать функцию AJAX для отправки данных.

$("#add_new_job_type").click(function(){ 
    $.ajax({ 
     url: '/add_new_job_type', 
     type: 'GET', // or POST 
     data: {job_type: $("#field_contains_new_value").val()} 
    }).done(function(data){ 
     // Do some validation for checking error response (like if statement) 
     // Append the new data (job type to select option tag) 
     new_job_type = "<option value="'+data.title+'">" + data.title + "</option>" 
     $('#job_job_type_id').append(new_job_type); 
     .... 
     $("#myModal").modal('hide'); 
    }); 

}); 

Примечание: add_new_job_type, используемое в AJAX URL это пользовательские маршруты.

В конфигурации/routes.rb (пользовательских маршрутов):

match 'add_new_job_type' => 'job_types#add_new_job_type', :via => :post #or :get 

В вашем JobTypes контроллер, вы должны иметь:

def add_new_job_type 
    job_type = JobType.new 
    job_type.title = params[:job_type] 
    if job_type.save 
    render :json => job_type 
    else 
    render :json => "some error here." 
    end 
end 

Измените код, как вы хотите.

+0

Что вы подразумеваете под: установка/проверка маршрутов/URL-адресов, которые будут использоваться для метода AJAX. ?? Можете ли вы объяснить свой ответ больше? –

+0

Привет @MoatazZaitoun, если у вас есть ресурсы: job_types в config/routes.rb, путь по умолчанию для метода create «/ job_types/new». Я сделаю для вас индивидуальные маршруты. Проверьте обновленный код. –

0

Если я могу предложить альтернативу ...

Ваш подход будет требовать некоторые дополнительные методы кодирования и, если вы плохо знакомы с AJAX, это может быть трудный путь.

В качестве альтернативы, я бы предположил, что вместо того чтобы показывать модальный, просто показать/скрыть текстовое поле в рамках существующей формы для размещения Другого названия:

<input type="text" name="other_job_type" /> 

Затем, когда вы отправите форму, а вы знаете, что он перейдет на JobController # create (или #update для существующих заданий). Там, вы можете получить это поле:

def create 
    save_successful = false 
    @job = Job.new params[:job] 
    other_job_type = params[:other_job_type] 
    if other_job_type 
    new_job_type = JobType.new 
    new_job_type.name = other_job_type 
    save_successful = new_job_type.save 
    @job.job_type = new_job_type 
    end 
    if save_successful && @job.save 
    # redirect to success page 
    else 
    # render new/edit with error messages 
    end 
end 

Делая это таким образом, вы только создать новый тип задания, если пользователь фактически отправляет форму задания, что приятно.

Используйте шаблон save_successful, если вы хотите принудительно выполнить проверки на JobType, например уникальное имя. Затем сохранение завершится неудачно, если пользователь попытается сохранить существующий тип задания. Вы также можете просто выбрать существующий для них, но я оставлю это вам, если вы решите это сделать.

Опять же, все это следует тому же шаблону, который вы используете сейчас, просто новое текстовое поле и немного больше обработки в контроллере.

Если вы хотите, я могу детализировать ответ на ваш вопрос с точки зрения использования методов AJAX, чтобы заставить его работать, поскольку этапы, хотя и намного длиннее, довольно детерминированные, но это, вероятно, слишком велико для вашего случая использования. Тем не менее, я ненавижу, что на самом деле не отвечаю на данный вопрос, независимо от моего личного мнения о подходе, поэтому просто дайте мне знать.

+0

Я действительно надеюсь, что вы ответите на него, используя AJAX –

Смежные вопросы