Last active
September 8, 2018 08:58
-
-
Save julianrubisch/c733d72f6bad9233d9f7bbaf95db525a to your computer and use it in GitHub Desktop.
DRY up an Inline-Text-Edit component with Partials, Capture, and a StimulusJS controller
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- downcase_modelname = model.class.name.downcase | |
- url = Rails.application.routes.url_helpers.send("#{downcase_modelname}_path", model, format: :json) | |
div[class="#{wrapper_class}" data-controller="inline-edit" data-inline-edit-url="#{url}" data-inline-edit-model="#{downcase_modelname}" data-inline-edit-model-attribute="#{attribute}" data-inline-edit-model-id="#{model.id}"] | |
span[data-target="inline-edit.originalText" id="#{attribute}-original"] | |
span = capture(attribute, &block) | |
a.inline-edit-edit-button[data-action="inline-edit#handleShow"] | |
i.fas.fa-edit | |
= simple_fields_for model do |f| | |
.ui.form.mini.hidden[data-target="inline-edit.form" id="#{attribute}-form"] | |
.ui.inline.fields | |
= f.input attribute, wrapper_html: { class: 'twelve wide field' }, input_html: { data: { action: 'keydown->inline-edit#handleKeyUp', target: 'inline-edit.textField' } }, label: false | |
= f.button :button, class: 'ui negative mini icon button', data: { action: 'inline-edit#handleCancel' } do | |
i.fas.fa-times | |
= f.button :button, class: 'ui positive mini icon button', data: { action: 'inline-edit#handleSubmit' } do | |
i.fas.fa-check | |
.ui.red.pointing.above.label.error.hidden.inline-edit-error-label[data-target="inline-edit.errorLabel"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.inline-edit-edit-button { | |
margin-left: 1rem; | |
} | |
.inline-edit-error-label { | |
margin-top: -1rem !important; | |
} | |
[data-controller="inline-edit"] { | |
.hidden { | |
display: none; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# from https://stackoverflow.com/a/27367024/4341756 | |
def inline_edit_form_for(model, attribute, wrapper_class, &block) | |
render partial: 'common/inline_text_edit', | |
locals: { | |
model: model, | |
attribute: attribute, | |
wrapper_class: wrapper_class, | |
block: block | |
} | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Controller } from "stimulus"; | |
import Rails from 'rails-ujs'; | |
export default class extends Controller { | |
static targets = [ 'form', 'originalText', 'textField', 'errorLabel' ]; | |
handleShow(e) { | |
e.preventDefault(); | |
this._showForm(); | |
} | |
handleCancel(e) { | |
e.preventDefault(); | |
this.textFieldTarget.value = this.originalTextTarget.querySelector('.inline-text-edit-target').innerText; | |
this.clearAndHide(); | |
} | |
clearAndHide() { | |
this.textFieldTarget.parentElement.classList.remove('error'); | |
this.errorLabelTarget.classList.add('hidden'); | |
this._hideForm(); | |
} | |
handleSubmit(e) { | |
e.preventDefault(); | |
this._submitForm(); | |
} | |
_hideForm() { | |
this.originalTextTarget.classList.remove('hidden'); | |
this.formTarget.classList.add('hidden'); | |
} | |
_showForm() { | |
this.originalTextTarget.classList.add('hidden'); | |
this.formTarget.classList.remove('hidden'); | |
} | |
_submitForm() { | |
const formData = { | |
[this.data.get('model')]: { | |
id: this.data.get('model-id'), | |
[this.data.get('model-attribute')]: this.textFieldTarget.value | |
} | |
}; | |
fetch(this.data.get('url'), { | |
credentials: 'same-origin', | |
method: 'PUT', | |
headers: { | |
'Content-Type': 'application/json', | |
'X-CSRF-Token': Rails.csrfToken() | |
}, | |
body: JSON.stringify(formData) | |
}) | |
.then(response => { | |
if (!response.ok) { | |
throw response; | |
} | |
return response; | |
}) | |
.then(response => response.json()) | |
.then(json => { | |
this.originalTextTarget.querySelector('.inline-text-edit-target').innerText = json[this.data.get('model-attribute')]; | |
this.clearAndHide(); | |
}) | |
.catch(err => { | |
err.json().then(err => { | |
this.textFieldTarget.parentElement.classList.add('error'); | |
this.errorLabelTarget.innerText = err[this.data.get('model-attribute')]; | |
this.errorLabelTarget.classList.remove('hidden'); | |
}); | |
}) | |
} | |
handleKeyUp(e) { | |
if (e.keyCode === 13) { | |
this._submitForm(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
= inline_edit_form_for(client, :name, 'ui header') do |attrib| | |
span.inline-text-edit-target = c[attrib] | |
= inline_edit_form_for(client, :website, 'sub header') do |attrib| | |
=< link_to c[attrib], "http://#{c[attrib]}", class: 'inline-text-edit-target' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment