Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow the input element name to be updated #381

Closed
wants to merge 2 commits into from

Conversation

joesolly
Copy link

@joesolly joesolly commented Mar 16, 2017

Useful when using formset's in Django. Will attempt to find the element set by the name but if it does not exist, set's the element id to the default Django id format.

this connects to islco/django-trix#2

Useful when using formset's in Django. Will attempt to find the element set by the name but if it does not exist, set's the element id to the default Django id format.
@javan
Copy link
Contributor

javan commented Mar 18, 2017

I'm not familiar with Django. Can you explain the problem with before and after HTML examples? Also, would creating your own input element help? Trix will only create its own if you don't point it to an existing input element like:

<trix-editor input="my_input"></trix-editor>
<input type="hidden" id="my_input">

@joesolly
Copy link
Author

Hi @javan , Thanks for taking the time to take a look at my PR!
When a model has a many-to-one (or many-to-many) relationship to another model, you can use what is called a FormSet to add the linked models to the initial one. Since you don't know how many new models you might be creating, Django creates a template form that get's copied and modified via JS to add new forms to the page.

So the template form would look something like this:

<tr class="form-row row2  empty-form" id="cards-empty">
<td class="field-content">
<textarea id="id_cards-__prefix__-content" name="cards-__prefix__-content" style="visibility: hidden; position: absolute;"></textarea><p><trix-editor input="id_cards-__prefix__-content" class="trix-content"></trix-editor></p>
</td>
<td class="delete"></td>
</tr>

When you request a new form, Django copies this template form and goes through each field on the form-row. As it does, it sets the id, name, and for properties (if they exist) to replace the "prefix" with the form's id number. This is where I ran into two issues.

  1. The trix-editor element doesn't have a setter for name, only a getter. So I added a setter to grab the element named by the setter and set that element's id as the trix-editor's new input value.
<textarea id="id_cards-2-content" name="cards-2-content" style="visibility: hidden; position: absolute;"></textarea><p><trix-editor input="id_cards-__prefix__-content" class="trix-content"></trix-editor></p>

trixEl.name = "cards-2-content"; // this fails now
// so instead trixEl.name setter now does this:
trixEl.name = function(name) {
  trixEl.input = document.getElementsByName(name)[0].id;
}
  1. Then I ran into the issue that Django doesn't add the new form fields into the DOM until after it finishes processing all of the fields. So document.getElementsByName(name)[0].id; fails because there are no inputs with that name. So I used the standard Django id formatting as a fallback.
trixEl.name = "cards-2-content"; // this fails now
// so instead trixEl.name setter now does this:
trixEl.name = function(name) {
  var inputElement = document.getElementsByName(name)[0];
  if (inputElement) {
    trixEl.input = inputElement.id;
  } else {
    trixEl.input = "id_" + name;
  }
}

// which should now successfully get the output of
<textarea id="id_cards-2-content" name="cards-2-content" style="visibility: hidden; position: absolute;"></textarea><p><trix-editor input="id_cards-2-content" class="trix-content"></trix-editor></p>

Please let me know if you have any more questions or any suggestions.

@javan
Copy link
Contributor

javan commented Mar 28, 2017

Could you put together a little example Django app that uses Trix (without your modifications) so I can see the problem in action?

@joesolly
Copy link
Author

hi @javan
I put together a sample for you. The repo is here: https://github.com/istrategylabs/trix_test
and you can see it in the django admin at this link: https://trix-test.herokuapp.com/admin/trix_test/parent/1/change/
You can log in with the username/password: test/test
The javascript from Django in question is this: https://github.com/django/django/blob/1.10.6/django/contrib/admin/static/admin/js/inlines.js#L34

@javan
Copy link
Contributor

javan commented Mar 29, 2017

Thanks! I don't think it makes sense to update Trix to work around an issue with Django's questionable admin JavaScript.

Here's a potential solution you could add to your app or to the django-trix widget. I tested with the example app you created and it seems to work.

addEventListener("trix-initialize", function(event) {
  var trixElement = event.target
  if (trixElement.getAttribute("input") == "id_child_set-__prefix__-content") {
    var inputElement = trixElement.closest(".field-content").querySelector("textarea")
    trixElement.setAttribute("input", inputElement.id)
  }
})

@javan javan closed this Jun 15, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants