Giter Site home page Giter Site logo

stimulus-components / stimulus-rails-nested-form Goto Github PK

View Code? Open in Web Editor NEW
102.0 4.0 22.0 417 KB

A Stimulus controller to create new fields on the fly to populate your Rails relationship.

Home Page: https://stimulus-rails-nested-form.stimulus-components.com

License: MIT License

JavaScript 7.06% HTML 71.98% TypeScript 20.59% CSS 0.38%
stimulusjs stimulus-controller stimulus-js npm-package snowpack

stimulus-rails-nested-form's Introduction

Stimulus components

๐Ÿ‘‰ Introducing Stimulus components.

๐Ÿ“š Documentation

See Stimulus Components Website.

๐Ÿ‘ท Contributing

Do not hesitate to contribute to the controllers by adapting or adding features ! Bug reports or pull requests are welcome.

Don't forget to drop a ๐ŸŒŸ on GitHub to support the project.

๐Ÿ“ License

This project is released under the MIT license.

stimulus-rails-nested-form's People

Contributors

dacook avatar guillaumebriday avatar michaelbaudino avatar sho918 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

stimulus-rails-nested-form's Issues

Allow minimum/maximum configuration

Cocoon would allow developers to define a minimum and maximum number of nested forms, would be nice to do the same here without extending the controller.

i.e. minimum = 1, maximum = 4

If only one nested form is being displayed then the delete button is hidden or disabled
If 4 are being displayed then the add button is hidden or disabled

Having a double nested form?

Hi!
I'm new to Stimulus, and I have a little issue trying to use the nested form component.

I have a survey model with many questions, and my question model has many answers.
I want to be able to create a survey, and add both questions & answers on the same view.

It works okay with a level 1 nesting (for the questions) but, I'm have a hard time adding the answer logic to it.
When I'm adding an answer, it duplicates the creation of a question, I know it has to come from the way the target are set-up, but I can't find a way to have both actions being separated (a button to create a question, and one to create an answer).

I followed up this tutorial to do so, but he does not seems to encounter this issue.

Here is my initial _form :

`<%= simple_form_for ([@survey]), data: { controller: 'nested-form', nested_form_wrapper_selector_value: '.nested-form-wrapper' } do |f| %>
  <template data-nested-form-target="template">
    <%= f.simple_fields_for :questions, Question.new, child_index: 'NEW_RECORD' do |question| %>
      <%= render "question_fields", f: question %>
    <% end %>
  </template>

  <%= f.fields_for :questions do |question| %>
    <%= render "question_fields", f: question %>
  <% end %>

  <!-- Inserted elements will be injected before that target. -->
  <div data-nested-form-target="target">
    <%= f.button :submit, "Add question", data: {action:"nested-form#add"} %>
  </div>

  <%= f.submit 'Create survey' %>
<% end %>`

My _question partial :


<div class="nested-form-wrapper" data-new-record="<%= f.object.new_record? %>">
  <%= f.input :body, label: "Question" %>
  <%= f.button :submit, "Delete question", data: {action:"nested-form#remove"} %>
  <%= f.hidden_field :_destroy %>
</div>

<template data-nested-form-target="template">
  <%= f.simple_fields_for :answers, Answer.new, child_index: 'NEW_RECORD' do |answer| %>
    <%= render "answer_fields", f: answer %>
  <% end %>
</template>

  <%= f.fields_for :answers do |answer| %>
    <%= render "answer_fields", f: answer %>
  <% end %>

  <!-- Inserted elements will be injected before that target. -->
  <div data-nested-form-target="target"></div>

  <%= f.button :submit, "Add answer", data: {action:"nested-form#add"} %>

And my _answer partial :

<div class="nested-form-wrapper" data-new-record="<%= f.object.new_record? %>">
  <%= f.input :body, label: "Answer" %>
  <%= f.button :submit, "Delete answer", data: {action:"nested-form#remove"} %>
  <%= f.hidden_field :_destroy %>
</div>

If anybody had this issue before, it would love to know how you dealt with it, thanks!

Possible to add first nested resource only after user clicked Add?

Sorry I am not sure this should be in the Issues, but there is no Discussions available.

With current example from the documentation, a new nested resource will always be created when the user first visits the page.

  <template data-nested-form-target="template">
    <%= f.fields_for :todos, Todo.new, child_index: 'NEW_RECORD' do |todo_fields| %>
      <%= render "todo_form", f: todo_fields %>
    <% end %>
  </template>

  <%= f.fields_for :todos do |todo_fields| %>
    <%= render "todo_form", f: todo_fields %>
  <% end %>

An empty Todo item will always be created and displayed on the page this way. But what if I needed to create a new Todo item only after the user clicked the Add button?

Mulitple Nested forms in same view?

Hi, trying to embed two nested forms in the same view (tags and pictures).

Is that a possible thing to with this component as it is today?

Avoid duplicating fields (maybe not an Issue)

Hi,

I just introduced this complenent to my pet project and found that it works well, except for the fact that I can't find a way to avoid creating duplicate records when adding more nested fields - I'm using it to select associated skills to training drills.

Form:

<%= javascript_pack_tag "application" %>
<%= form_with model: drill, data: { controller: 'nested-form', nested_form_wrapper_selector_value: '.nested-form-wrapper' } do |form| %>
        <template data-nested-form-target="template">
	       <%= form.fields_for :skills, Drill.new, child_index: 'NEW_RECORD' do |skill_fields| %>
			<%= render 'skill_form', form: skill_fields %>
		<% end %>
	</template>
	<%= form.fields_for :skills do |skill_fields| %>
		<%= render 'skill_form', form: skill_fields %>
	<% end %>
	<div data-nested-form-target="target"></div>
	<button type="button" data-action="nested-form#add">Add</button>

(SKILL PARTIAL)

<div class='nested-fields'>
  <div class='form-group'>
    <%= form.hidden_field :_destroy %>
	<%= form.text_field :name, placeholder: 'Fundamento', class: 'form-control', size: 10 %>
	<button style="height:32px;width:32px" type="button" data-action="nested-form#remove"><%= image_tag "minus.png" %></button>
  </div>
</div>

Can't import the named export 'Controller' from non EcmaScript module

I've added these lines in app/webpacker/controllers/index.js as per the instructions:

import NestedForm from 'stimulus-rails-nested-form';
...
application.register('nested-form', NestedForm);

But getting this compilation error and don't know how to fix it:

./node_modules/stimulus-rails-nested-form/dist/stimulus-rails-nested-form.mjs 42:2-3
Can't import the named export 'Controller' from non EcmaScript module (only default export is available)

Environment

@hotwired/stimulus@^3.2.2
webpack@^4.46.0
rails (7.0.8)
node-version 17.9.1 (Edit: I note that this component uses Node 18)

Unique Identifiers for Nested Form Fields to Prevent Data Overwrite

When using the stimulus-rails-nested-form library to dynamically add nested form fields, it has been observed that if the "add" action is triggered multiple times, the newly added input fields end up having the same name attribute value. This behavior results in only the last input's data being submitted, as the preceding input values are overwritten due to the shared name attribute among them. This issue fundamentally affects the form's ability to correctly handle multiple nested records, leading to data loss and inconsistent submissions.

I propose modifying the nested form field addition process to include a unique identifier within each name attribute of newly added input fields. This can be achieved by appending a timestamp or a sequentially incremented value to the name attribute, ensuring its uniqueness across the form. I have prepared a pull request that implements this solution by extending the current functionality of the stimulus-rails-nested-form library's controller to include this adjustment.

I''ll send a PR

Failed to resolve module specifier 'controllers/nested_form_controller'

Hi, I am using nested_form but I have a error.

I am using rails7 and importmap (pin)

I have this error on browser console
Error
Failed to autoload controller: nested-form TypeError: Failed to resolve module specifier 'controllers/nested_form_controller'

Form is working but I want to clear this error.

Can you help me?

Importmap.rb
pin "stimulus-rails-nested-form", to: "https://ga.jspm.io/npm:[email protected]/dist/stimulus-rails-nested-form.es.js"

application.js
import NestedForm from 'stimulus-rails-nested-form'
application.register('nested-form', NestedForm)

Use with Rails 7?

I am migrating my application to Rails 7 with importmap but this seems to break the nested form feature. Any ideas on how to bridge this issue?

Bug with double nested forms

I think there's bug when using in a form with multiple nested associations. Like a Survey -> Questions -> Answers situation for example.

When clicking Remove the code here https://github.com/stimulus-components/stimulus-rails-nested-form/blob/master/src/index.ts#L34 will grab the first _destroy input which in a double nested situation might be wrong (depends on where you put the remove button) and you'll end up removing a nested child instead of the parent child sometimes.

If the line instead is written like

const input = wrapper.querySelector(":scope > input[name*='_destroy']")

everything works but the precludes that the input element is a direct descendent of the wrapper class. Not sure what the ideal fix would be.

[ASK] If new nested form returning same child_index value?

Screen.Recording.2024-06-21.at.17.54.01.mov

Hello, I have a question. When I press add content on existing section it does appearing unique child_index of material, meanwhile when I press add new section then add new content the child index not unique anymore, what is wrong with my code?

  1. forms/_contents.html.erb
<div class="mb-4">
  <div class="pb-3">
    <span class="fs-16 bold">Course contents</span>
  </div>
  <div data-controller="nested-form" data-nested-form-wrapper-selector-value=".section-form-wrapper">
    <template data-nested-form-target="template" data-model-template="section">
      <%= form_content.fields_for :sections, Course::Section.new, child_index: 'NEW_RECORD' do |section_fields| %> 
        <%= render "forms/section", f: section_fields %> 
      <% end %>
    </template>
  
    <%= form_content.fields_for :sections do |section_fields|%> 
      <%= render "forms/section", f: section_fields %> 
    <% end %>
  
    <div data-nested-form-target="target" data-model-target="section"></div>
  
    <div
      style="
        border: 1px dashed #3b43f1;
        color: #3b43f1;
        width: 100%;
        border-radius: 5px;
        text-align: center;
      "
      class="p-2"
    >
      <%= link_to "+ Add section", "#", data: { action: "nested-form#add", model: "section" } %>
      <!-- <button class="" , data-action="nested-form#add">+ Add section</button> -->
    </div>
  </div>
</div>
  1. forms/_section.html.erb
<div class="section-form-wrapper" data-new-record="<%= f.object.new_record? %>">
  <div
    class="col-lg-12 p-3"
    style="
      background: #e0e0ff;
      border-top-left-radius: 5px;
      border-top-right-radius: 5px;
    "
  >
    <div class="d-flex justify-content-between align-items-center">
      <span class="fs-16 bold">Section <%#= f.options[:child_index] %></span>
      <div class="d-flex gap-2">
        <button
          class="btn btn-outline-danger d-flex gap-2"
          data-action="nested-form#remove"
          data-model="section"
          style="background: #fff"
        >
          <%= image_tag("icon-del-red.svg", alt: "") %>
          <span>Remove</span>
        </button>
        <%= f.hidden_field :_destroy %>
      </div>
    </div>
  </div>
  <div class="card-custom">
    <div class="p-3">
      <div class="mb-3">
        <label class="form-label">Section name</label>
        <%= f.text_field :name, class: "form-control", placeholder: "Enter section name" %>
      </div>

      <div class="mb-3">
        <label class="form-label">Section subtitle</label>
        <%= f.text_field :subtitle, class: "form-control", placeholder: "Enter section subtitle" %>
      </div>

      <div class="mb-3">
        <label class="form-label">Long description</label>
        <%= f.text_area(:description, rows: 3, class: "form-control",
          placeholder:"Enter short description", style: "height: 128px")%>
      </div>
    </div>

    <div class="divider"></div>
    <div class="mb-4 px-3 pb-3">
      <div class="d-flex justify-content-between align-items-center">
        <p class="fs-16 bold m-0 mt-3">Materials</p>
        <!-- <button class="btn btn-active d-flex gap-2 align-items-center">
          <span class="text-primary fs-14">Collapse</span>
          <%#= image_tag("chevron-up.svg", alt: "") %>
        </button> -->
      </div>
      <p class="m-0 fs-14 font-grey">Upload materials for the participants</p>
  
      <div data-controller="nested-form" data-nested-form-wrapper-selector-value=".material-form-wrapper">
        <template data-nested-form-target="template" data-model-template="material">
          <%= f.fields_for :materials, Course::Material.new, child_index: 'NEW_RECORD' do |material_fields| %> 
            <%= material_fields.options[:child_index] %>
          <% end %>
        </template>

        <%= f.fields_for :materials do |material_fields, index|%>
          <%= material_fields.options[:child_index] %>
        <% end %>

        <div data-nested-form-target="target" data-model-target="material"></div>

        <button class="btn btn-outline-primary mt-2" , data-action="nested-form#add">+ Add content</button>
      </div>
    </div>
  </div>
</div>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.