Встроенное редактирование с помощью Rails gem 'best_in_place' - ошибка: новые строки теряются после редактирования на textarea

Я использую best_in_place gem, чтобы сделать некоторое встроенное редактирование в приложении Rails.

Одно из свойств моего объекта имеет тип text, и я хочу, чтобы он редактировался в текстовой области, поэтому я сделал это:

<%= best_in_place @myobject, :description, :type => :textarea %>

Он работает, но когда он не редактируется, все возвраты (\n) удаляются.

Я попытался использовать simple_format, добавив :display_with => :simple_format к параметрам, переданным в best_in_place:

<%= best_in_place @myobject, :description, :type => :textarea, :display_with => :simple_format %>

При отсутствии редактирования новые строки отображаются в соответствии с ожиданиями. Но щелчок, чтобы войти в редакцию, сломан, и новая черта добавлена ​​выше. Нажатие на него отображает текстовое поле, но оно пустое, а введенный там текст не сохраняется обратно к моему объекту.

Содержимое, сохраненное в моем свойстве, - это просто текст, он не содержит html.


Эта проблема (и исправление), казалось, была связана с моей проблемой: https://github.com/bernat/best_in_place/pull/111
Однако при применении патча (вручную, в файле .../gems/best_in_place-1.0.6/spec/spec_helper.rb) у меня все еще есть та же проблема.

Ответ 1

У меня была такая же проблема, и я решил ее привязать к событию "ajax: success", как описано в best_in_place documentation и преобразовании нового строк до <br />.

$('.best_in_place').bind('ajax:success', function(){ this.innerHTML = this.innerHTML.replace(/\n/g, '<br />') });

Вы также можете использовать легкий язык разметки, например, текстиль или уценку вместо простых разрывов строк. Javascript-конвертеры для них можно найти здесь (текстиль) и здесь (уценка).

Я пошел с Textile, так как я мог просто использовать метод textilize в опции best_in_place display_with.

Обновленный javascript:

$('.best_in_place').bind('ajax:success', function(){ $(this).JQtextile('textile', this.innerHTML) });

Кроме того, если вы хотите только этого поведения в текстовых областях best_in_place, вы можете проверить атрибут типа данных:

$('.best_in_place').bind('ajax:success', function(){ 
    if ($(this).attr('data-type') == 'textarea')
        $(this).JQtextile('textile', this.innerHTML) 
});

Наконец, сопоставьте конверсию со стороны сервера:

:display_with => lambda { |v| textilize(v).html_safe } // the RedCloth gem may be required.

Ответ 2

Нашел полурабочее решение.

В show.html.erb:

<%= best_in_place @myobject, :description, :type => :textarea, :display_as => 'description_format'  %>

и в myobject.rb:

def description_format
  self.description.gsub(/\n/, "<br>")
end

Работает так, как ожидалось. Почти.
Единственная оставшаяся проблема: когда вы редактируете текст, после того, как вы не сфокусировались на текстовом поле, новые строки снова теряются. Если вы обновите страницу, она будет отображаться правильно.

Ответ 3

Если \n заменяется на <br>, и пользователь решает сделать больше изменений, пользователь увидит весь текст только на одной строке, что затруднит чтение и редактирование.

Основываясь на ответах выше, я сделал это решение, которое удаляет любой \r после успеха.

$('.best_in_place').bind('ajax:success', function(){ 
    if ($(this).attr('data-type') == 'textarea') {
        this.innerHTML = this.innerHTML.replace(/\r/g, '')
    }
});

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

Ответ 4

Я думаю, что ответы здесь все работают. Это еще одна альтернатива. Вы можете добавить поле best_in_place между тегом <pre> и позаботиться о добавлении строк. Конечно, потребуется некоторое форматирование и изменение стиля, но оно легко решает проблему.

Ответ 5

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

В форме:

div class: "single-spacing", id: "comment_div" do
    best_in_place coursedate, :comment, as: :textarea, url: [:admin,coursedate], ok_button: "Uppdatera", cancel_button: "Cancel", class: "editable", 
     :display_with => lambda { |c| simple_format(c.gsub("<br />", ""), {}, sanitize: false) }
end

В css:

.single-spacing {
  ul br {
   display: none;
 }
  ol br {
  display: none;
 }
  div br {
   display: none;
  }
h3 {
  border-bottom: 1px dotted #e8e8e8;
   padding-bottom: 15px;
}
 blockquote {
   border-color: #a7c2d9;
    p {
      font-size: 14px;
      color: #777777;
      line-height: 1.5;
    }
  }
}

CoffeeScript:

# refresh textarea bip on coursedate when edited to reload line breaks after update
  $('#comment_div').bind 'ajax:success', ->
  $('#comment_div').load(document.URL +  ' #comment_div');
  return

Ответ 6

Это помогло мне.

  $('.best_in_place').bind 'ajax:success', -> 
    content = $(this).text().replace(/\n/g, "<br>")
    $(this).html(content)

или JQuery

$('.best_in_place').bind('ajax:success', function(){ 
    content = $(this).text().replace(/\n/g, "<br>")
    $(this).html(content)
});