Trix: Toolbar Buttons affect all instances on page in Chrome

Created on 1 Sep 2016  路  5Comments  路  Source: basecamp/trix

I'm using Knockout.js to dynamically create an editor instance for each item in my collection. I'm experiencing problems the toolbar buttons from one instance affecting other instances. Specifically, if multiple instances are on page:

  1. Only the first instance's toolbar works.
  2. Clicking a block-level toolbar button causes a change in all instances.
  3. Focus is always given to the last instance's editable area.

I'm glad to try and debug if someone could point me in the right direction.

Steps to Reproduce

See this CodePen for a reproduction of the issue. I'm seeing this issue in Chrome. Works fine in Safari 9.1

Details
  • Trix version: 0.9.7
  • Browser name and version: Chrome 52
  • Operating system: OS X 10.11

Most helpful comment

If you look at the HTML that's generated for by your loop:

<div data-bind="foreach: models">
 <trix-toolbar id="trix-toolbar-1"></trix-toolbar>
 <trix-editor contenteditable="" trix-id="1" input="trix-input-1" toolbar="trix-toolbar-1"></trix-editor>
 <input type="hidden" id="trix-input-1">

 <trix-toolbar id="trix-toolbar-1"></trix-toolbar>
 <trix-editor contenteditable="" trix-id="1" input="trix-input-1" toolbar="trix-toolbar-1"></trix-editor>
 <input type="hidden" id="trix-input-1">

 <trix-toolbar id="trix-toolbar-1">
 </trix-toolbar><trix-editor contenteditable="" trix-id="1" input="trix-input-1" toolbar="trix-toolbar-1"></trix-editor>
 <input type="hidden" id="trix-input-1">
</div>

All the toolbar IDs and the toolbar attributes are the same. If you give each <trix-editor> a unique ID, each editor/toolbar pair should work as a unit.

All 5 comments

If you look at the HTML that's generated for by your loop:

<div data-bind="foreach: models">
 <trix-toolbar id="trix-toolbar-1"></trix-toolbar>
 <trix-editor contenteditable="" trix-id="1" input="trix-input-1" toolbar="trix-toolbar-1"></trix-editor>
 <input type="hidden" id="trix-input-1">

 <trix-toolbar id="trix-toolbar-1"></trix-toolbar>
 <trix-editor contenteditable="" trix-id="1" input="trix-input-1" toolbar="trix-toolbar-1"></trix-editor>
 <input type="hidden" id="trix-input-1">

 <trix-toolbar id="trix-toolbar-1">
 </trix-toolbar><trix-editor contenteditable="" trix-id="1" input="trix-input-1" toolbar="trix-toolbar-1"></trix-editor>
 <input type="hidden" id="trix-input-1">
</div>

All the toolbar IDs and the toolbar attributes are the same. If you give each <trix-editor> a unique ID, each editor/toolbar pair should work as a unit.

@jeffreyguenther, that is a fair statement. However, I don't have an early-enough hook that I can set the id _before_ the trix-editor element is expanded. Again, this works as expected in Safari and Firefox. I've updated my CodePen to show what happens when I try and dynamically set the id.

Generally, you'll want to avoid using an actual <trix-editor> DOM node as a template because it automatically installs the editor when attached. I'm not really familiar with knockout.js, but this seems to fix your problem. Uses a template instead of an element.

<div data-bind="template: { name: 'editor-template', foreach: models }"></div>

<script type="text/html" id="editor-template">
  <trix-editor></trix-editor>
</script>

Thanks so much @javan. Loving Trix so far.

SOLUTION: add unique ID with trix-id="unique_id_here"

Ex:
<trix-editor angular-trix ng-model="model.text.here" trix-id="{{$index}}"></trix-editor>

Above $index come from the ng-repeate

Was this page helpful?
0 / 5 - 0 ratings