@mentions for Users with ActionText; 使用Tribute.js庫

git clone從https://github.com/chentianwei411/at-mentions-with-action-textjavascript

 

先fork下來,而後拷貝https鏈接,最後在terminal上:html

git clone https://github.com/chenwei/at-mentions-with-action-text.gitjava

而後由於ruby 和 rails版本。使用命令:webpack

rvm 2.6.1@railsXXX版本 
#簡單的集合命令,詳細看以前的相關博客。

根據提示安裝bundler和yarn更新。git

10821  gem install bundler:2.0.1
10822  bundle update
10828  yarn install --check-files

 

最後rails db:migrate並rails s啓動服務器localhost:3000github

 


rails6.1後: Module#parent_name幫助方法被替換:

    # config.application_name = Rails.application.class.parent_name
    config.application_name = Rails.application.class.module_parent_name

 


 

 

實作@mention功能

使用tribute庫來實現@mention功能,支持Vue。web

參考https://zurb.github.io/tribute/example/案例,在輸入框輸入@能夠顯示人名的下拉列表。數據庫

 

trix文本編輯器已經被集成到新版本。json

使用stimulus.js增長JavaScript腳本。api

rails webpacker:install:stimulus

 

而後下載ZURB tribute javascript library。這裏使用yarn,也能夠用gem 'tribute'

https://github.com/zurb/tribute

這是用ES6寫的@mention引擎。無需依賴dependencies。跨瀏覽器。

yarn add tributejs

 

按照路徑->controller->view思路:

routes.rb內添加:

resources :mentions, only: [:index]

目的是點擊這個url來自動獲取users。而後就能夠動態地load. json格式的user數據。👇

 

建立 controllers mentions controller

class MentionsController < ApplicationController
  def index
    @users = User.all

    respond_to do |format|
      format.json
    end
  end
end

⚠️,演示是取所有的user,實際上線版本只取通常前10個用戶名字。

 

建立views/mentions/index.json.jbuilder

json.array! @users, partial: "users/users", as: :user

 

獲得一個array of users, 而後返回partial, 數據名字是user。

 

建立app/views/users/_user.json.jbuilder

#從user提取它們的id , name
json.extract! user, :id, :name

json.sgid user.attachable_sgid
json.content render(partial: "users/user", locals: {user: user}, format: [:html])

 

解釋:

1. json.sgid user.attachable_sgid

須要在modles/User.rb內include一個模塊,以便使用方便的方法, 👆的user.attachable_sgid。

include ActionText::Attachable

2. json.conent。 渲染views/users/_user.html.erb,傳入數據user,格式是html。

 

建立views/users/_user.html.erb

<span class="mention">
  <%= image_tag gravatar_image_url(user.email, size: 40), height: 20, width: 20, class: "rounded" %>
  <%= user.name %>
</span> 
  1. 啓動服務器
  2. localhost:3000/mentions.json能夠看到從數據庫取得的用戶數據和渲染的視圖代碼。

 

下一步:修改post表格,在rich text area增長一個controller和target。

即便用Stimulus的data-target來取這個元素。

  <div class="form-group">
    <%= form.label :body %>
    <%= form.rich_text_area :body, class: 'form-control', data: { controller: "mentions", target: "mentions.field" } %>
  </div>

 

建立app/javascript/controllers/mentions_controller.js

import { Controller } from 'stimulus'

export default class extends Controller {
  static targets = ["field"]  #定位到post視圖的元素上。

  contect() {
  this.editor = this.fieldTarget.editor
  this.initializeTribute() #初始化tribute
}

initializeTribute() {
  ...
 } }

 

爲了使用Tribute須要import

...
import
Tribute from 'tributejs' import Trix from 'trix'
...
 

 

initializeTribute() {
  this.tribute = new Tribute({
    allowSpaces: true,            #集合中的方法,能夠在mentions中有空格
    lookup: 'name',               #集合中的方法,在對象中搜索對應的column(函數或字符串)
    values: this.fetchUsers,      #必須的(required)經過異步函數得到一個數組對象,用於匹配。
  })
this.tribute.attach(this.fieldTarget) #把tribute實例鏈接到元素上。
... }

 

異步函數:fetchUsers

fetchUsers(text, callback) {
   fetch(`/mentions.json?query=${text}`) 
   .then(response => response.json())
   .then(users => callback(users))
   .catch(error => callback([])) 
}    

 

當不須要監聽事件了用disconnect來從元素上移除Tribute實例:

  disconnect() {
    this.tribute.detach(this.fieldTarget)
  }

 

 

此時若是在http://localhost:3000/posts/1/edit上嘗試,會出現@undefined, 這是由於沒有實際 插入value。改用使用事件tribute-replaced。

在initializeTribute()函數內添加

    // 點擊後回退一個字符,即去掉@:
    this.tribute.range.pasteHtml = this._pasteHtml.bind(this)
    // 給目標元素添加事件,當完成
    this.fieldTarget.addEventListener("tribute-replaced", this.replaced)

 

添加函數replaced:

這裏要參考Trix api文檔:https://github.com/basecamp/trix

  replaced(e) {
    console.log(e)
    // 獲得事件中的數據
    let mention = e.detail.item.original
    // 建立Trix.Attachment,而後調用insertAttachment方法來插入HTML
    let attachment = new Trix.Attachment({
      sgid: mention.sgid,
      content: mention.content
    })
    this.editor.insertAttachment(attachment)
    // 再插入一個空格,具體見Trix Api.
    this.editor.insertString(" ")
  }

 

添加_pasteHtml函數:

  _pasteHtml(html, startPos, endPos) {
    let position = this.editor.getPosition()
    //2個Trix方法
    this.editor.setSelectedRange([position - endPos, position])
    this.editor.deleteInDirection("backward")
  }

 

一個bug: post更新後,再次編輯,@mention內容不可見。當前解決方法是在user.rb添加:

  def to_trix_content_attachment_partial_path
    to_partial_path
  end 

 

如何使用Tributejs庫(見git)

  1. 初始化new Tribute({ ... })
  2. 把Tribute附加到元素。如input, textarea。 例如:tribute.attach(元素的位置)
  3. lookup column。必填項,能夠是一個函數。
  4. 函數selectTemplate和menuItemTemplate用於存取item object,即當點擊選中的項目後,的顯示。
  5. 事件tribute-replaced。 能夠給目標元素綁定這個事件,用於知道什麼時候完成更新目標tribute元素
  6. 最後,不須要了,就detach Tribute實例,從元素上分開移除Tribute。使用tribute.detach(元素位置)。這會移除全部的實際監聽
相關文章
相關標籤/搜索