Syntax for form data elements using stimulus-library - ruby-on-rails

Reference document stimulus-library and its relevant example
Attempting to get the rich text area - also using mobility - wher the goal is to alter the trix-editor tag as follows:
<trix-editor
data-controller="trix-modifier"
data-no-file-uploads
></trix-editor>
the following fail
<%= form.rich_text_area "translatable_content_#{Mobility.normalize_locale(user_idioma.idioma.code.to_s)}", rows: 20,
data: { controller: 'trix-modifier'}, data: { 'no-file-uploads' } %>
<%= form.rich_text_area "translatable_content_#{Mobility.normalize_locale(user_idioma.idioma.code.to_s)}", rows: 20,
data: { controller: 'trix-modifier', 'no-file-uploads' } %>
while a simple controller element definition renders correctly:
<%= form.rich_text_area "translatable_content_#{Mobility.normalize_locale(user_idioma.idioma.code.to_s)}", rows: 20,
data: { controller: 'trix-modifier'} %>
how should the syntax be set to generate the proper tag impeding file uploads?

Posting this as a simple reference, figured out by poking around:
<%= form.rich_text_area "translatable_content_#{Mobility.normalize_locale(user_idioma.idioma.code.to_s)}", rows: 20,
data: { controller: 'trix-modifier', 'no-file-uploads' => true } %>

Related

Error with Rails Sortable - Cannot read properties of undefined (reading 'dataset')

I followed this tutorial to implement drag and drop. https://www.driftingruby.com/episodes/drag-and-drop-with-hotwire
I am getting an error on drop that says Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'dataset'). Any thoughts on why this is happening?
Project model:
acts_as_list scope: :project
_project.html.erb
<div id="projects" data-controller="position">
<%= content_tag :div, data: { sgid: project.to_sgid_param, id: "#{dom_id project}" }, class: 'table-row' do %> <div><%= project.name %> </div>
<div><%= project.description %> </div>
<div><%= project.status %> </div>
<div><%= project.user.email %> </div>
<div class="flex justify-end">
<%= link_to "View", project_path(project) , data: {turbo: false} %>
<%= button_to "Delete", project, method: :delete, form: {data: {turbo_confirm: "Are you sure?"}} %> </div>
</div>
<% end %>
</div>
position_controller.js
import { Controller } from "#hotwired/stimulus";
import Sortable from "sortablejs"
import { put, get, post, patch, destroy } from "#rails/request.js"
export default class extends Controller {
connect() {
this.sortable = Sortable.create(this.element, {
animation: 150,
onEnd: this.updatePosition.bind(this)
})
}
async updatePosition(event) {
const response = await put('/projects', {
body: JSON.stringify({
sgid: event.project.dataset.sgid,
position: event.newIndex + 1
})
})
if (response.ok) {
console.log(event.project.dataset.sgid)
}
}
}
well event doesn't have a method project. You may have meant event.target. Anyway it looks as if the target of the event is probably the #projects element (but you need to check this in dev tools and see where the event is being captured).
Let's suppose that the event is being captured by the #projects element, well that element has an empty dataList. So wherever the capture is occurring, you need to put data: {sgid: project.to_sgid_param} on that element.
Finally, you should be able to populate the ajax request with the value sgid: event.target.dataset.sgid.

Rails/Stimulus: What is the best way to get form field values when handling form submission with Stimulus?

I have a form but Stimulus will handle its submission.
<%= form_with model: #booking, data: { controller: 'booking', action: 'booking#submitForm:prevent' } do |form| %>
<%= form.text_field :name, data: { 'booking-target' => 'name' } %>
<%= form.text_field :pet_name, data: { 'booking-target' => 'pet' } %>
<%= form.submit "Submit form" %>
<% end %>
import { Controller } from "#hotwired/stimulus"
export default class extends Controller {
static targets = ['name', 'pet']
submitForm() {
console.log('Submitting form')
console.log('Name: ' + this.nameTarget.value)
console.log('Pet: ' + this.petTarget.value)
}
}
The above code works but I have specified the target name for each field in the form. This isn't a problem with a small form but would be cumbersome if the form had many more fields. Is there a more elegant way to expose the field data?
You don't have to specify targets and just use the form directly:
submitForm(e) {
// get it directly from the form
console.log(e.target.name, e.target.name.value)
// or like this
console.log(e.target["pet_name"], e.target["pet_name"].value)
// get everything
const data = Object.fromEntries(new FormData(e.target).entries())
console.log(data)
}
BTW, you can also do this:
# <%= form.text_field :name, data: { 'booking-target' => 'name' } %>
<%= form.text_field :name, data: { booking_target: :name } %>

Rails-7 : Prevent form clear on get request

My problem seems simple.
<%= form_with(url: projects_path, method: :get, data: { turbo_frame: "projects", turbo_action: "advance", controller: "search-form" }) do |form| %>
<%= form.text_field :title, data: { action: "input->search-form#search" } %>
<%= form.collection_select :category, Project.categories.keys, :to_s, :titlecase, { include_blank: true, default: 0 }, data: { action: "change->search-form#search" } %>
<%= form.submit "Search" %>
<% end %>
I've got this form that clears after submitting the get request. I need it to be Get because I'm using Turbo. Is there a way to prevent that via stimulus or simple Rails/Ruby ?
Here is my stimulus file if needed :
import { Controller } from "#hotwired/stimulus"
// Connects to data-controller="search-form"
export default class extends Controller {
search() {
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
this.element.requestSubmit();
}, 150)
}
}
Preventing the form to empty on an asynchronous request is good but surely when I submit every key stroke. xD
Thanks for the help !

How do I customize the number of rows in my rich_text_area for simple_form?

I am using SimpleForm 5.0.2 along with ActionText.
I would like the main body field of my form to be multiple rows (say 10), but I can't figure out how to get it to work.
This is my current attempt:
<%= f.rich_text_area :body, class: 'form-control', name: "article-text", input_html: { rows: 10 }, placeholder: "Enter your article body here..." %>
That produces this HTML:
<trix-editor class="form-control" input_html="{:rows=>10}" placeholder="Enter your article body here..." id="article_body" input="article_body_trix_input_article" data-direct-upload-url="http://localhost:3000/rails/active_storage/direct_uploads" data-blob-url-template="http://localhost:3000/rails/active_storage/blobs/:signed_id/:filename" contenteditable="" role="textbox" trix-id="1" toolbar="trix-toolbar-1"></trix-editor>
Which looks like this:
Note that I also tried various iterations of input_html:, including but not limited to:
<%= ... input_html: { 'rows': '10' } ... %>
<%= ... input_html: { rows: "10" } ... %>
All to no avail.
How do I get this working?
It looks like the rich_text_area only accepts :class option so the :input_html does nothing here. But because the height is decided by CSS, we can achive what you want by overrding the default min-height CSS of trix-editor.
In app/assets/stylesheets/actiontext.scss
trix-editor {
&.customized-min-height {
min-height: 15em;
}
}
In your view file
f.rich_text_area :body, class: "form-control customized-min-height"
You can set a min-height property for the trix editor, like so:
trix-editor {
&.form-control {
min-height: 20rem;
height: auto;
}
}

"unexpected '}', expecting =>" while using attributes

I have an img tag as html and I want to use it in erb:
<img src="images/Slider/app.png" alt="" width="636" height="441" data-ww="['600px','500px','400px','200px']" data-hh="['338px','281px','225px','113px']" data-no-retina>
my html erb code is:
<%= image_tag "/Slider/app.png", width:"636", height:"441", data: { ww:['600px','500px','400px','200px'], hh:['338px','281px','225px','113px'], no-retina } %>
but I get syntax error: unexpected '}', expecting =>
Rails does not allow dash-case as a hash key. Thus the syntax is failing when trying to parse no-retina.
You should use lateral strings if you want to have a dash-case as a key
<%= image_tag "/Slider/app.png", width:"636", height:"441", data: { ww:['600px','500px','400px','200px'], hh:['338px','281px','225px','113px'], 'no-retina': true } %>
In this particular case (image_tag helper and data attributes), however, Rails is smart enough to get you the right HTML if you just use uderscores:
<%= image_tag "/Slider/app.png", width:"636", height:"441", data: { ww:['600px','500px','400px','200px'], hh:['338px','281px','225px','113px'], no_retina: true } %>
Also if you looks at the image_tag documentation, you will see that you can use size to specify height and width. With some code style cleanup this is what looks much better:
<%= image_tag "/Slider/app.png", size: "636x441", data: { ww: ['600px','500px','400px','200px'], hh: ['338px','281px','225px','113px'], no_retina: true } %>
You can break it by - and nest it
<%= image_tag "/Slider/app.png", data: { no: { retina: true } } %>

Resources