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

Cannot read properties of null (reading 'offset') on custom handler getSelection() #4375

Open
erodriguezg opened this issue Aug 14, 2024 · 3 comments

Comments

@erodriguezg
Copy link

I was trying to implement a custom handler for image loading, which gave me the following error:

quill.js?v=ad3ea11b:12611 Uncaught TypeError: Cannot read properties of null (reading 'offset')
at quill.js?v=ad3ea11b:12611:26
at Array.map ()
at Proxy.normalizedToRange (quill.js?v=ad3ea11b:12608:31)
at Proxy.getRange (quill.js?v=ad3ea11b:12597:25)
at Proxy.update (quill.js?v=ad3ea11b:12734:43)
at Proxy.update (quill.js?v=ad3ea11b:13811:20)
at Proxy.getSelection (quill.js?v=ad3ea11b:13705:10)
at Toolbar.imageHandler (EditPublicationPage.vue:42:31)
at HTMLButtonElement. (quill.js?v=ad3ea11b:17165:31)

I downgraded to 1.3.7 from 2.0.2 (also tested 2.0.1 and 2.0.0 with no success) and the same code now works flawlessly.

The Handler:

function imageHandler () {
if (quill.value) {
quill.value.focus()
const range = quill.value.getSelection() // this line throws error
const value = prompt('please copy paste the image url here.')
if (value) {
quill.value.insertEmbed(range.index, 'image', value, Quill.sources.USER)
}
}
}

all source code of my component:

``

<script setup lang="ts"> import { ref } from 'vue' import Editor, { EditorLoadEvent } from 'primevue/editor' import Quill from 'quill' const richContent = ref('') const toolbarOptions = [ ['bold', 'italic', 'underline', 'strike'], // toggled buttons ['blockquote', 'code-block'], ['link', 'image', 'video', 'formula'], [{ list: 'ordered' }, { list: 'bullet' }, { list: 'check' }], [{ script: 'sub' }, { script: 'super' }], // superscript/subscript [{ indent: '-1' }, { indent: '+1' }], // outdent/indent [{ size: ['small', false, 'large', 'huge'] }], [{ color: [] }, { background: [] }], // dropdown with defaults from theme [{ font: [] }], [{ align: [] }], ['clean'] // remove formatting button ] const quillModules = { toolbar: { container: toolbarOptions, handlers: { image: imageHandler } } } const quill = ref(null) function onLoadEditor (event: EditorLoadEvent) { quill.value = event.instance } function imageHandler () { if (quill.value) { quill.value.focus() const range = quill.value.getSelection() const value = prompt('please copy paste the image url here.') if (value) { quill.value.insertEmbed(range.index, 'image', value, Quill.sources.USER) } } } </script>
<h2 class="title">Crear Publicación</h2>

<div class="form-wrapper">
  <!-- Título -->
  <div>
    <label for="titulo">Título</label>
    <input type="text" id="titulo" name="titulo"
      class="mt-2 block w-full px-4 py-3 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-lg"
      placeholder="Ingrese el título">
  </div>

  <!-- URL de imagen banner -->
  <div>
    <label for="banner-url" class="block text-lg font-medium text-gray-700">URL Imagen Banner</label>
    <input type="url" id="banner-url" name="banner-url"
      class="mt-2 block w-full px-4 py-3 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-lg"
      placeholder="Ingrese la URL de la imagen">
  </div>

  <!-- Bajada -->
  <div>
    <label for="bajada" class="block text-lg font-medium text-gray-700">Bajada</label>
    <textarea id="bajada" name="bajada" rows="4"
      class="mt-2 block w-full px-4 py-3 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-lg"
      placeholder="Ingrese la bajada"></textarea>
  </div>

  <!-- Contenido enriquecido -->
  <div>
    <label for="contenido" class="block text-lg font-medium text-gray-700">Contenido Enriquecido</label>
    <Editor v-model="richContent" class="custom-editor" :modules="quillModules" @load="onLoadEditor">
    </Editor>
  </div>

  <!-- Botón de enviar -->
  <div class="flex justify-end">
    <button type="submit"
      class="inline-flex items-center px-6 py-3 border border-transparent text-lg font-medium rounded-lg shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">Publicar</button>
  </div>
</div>
<style lang="scss" scoped> :deep(.p-editor-toolbar) { display: none; } :deep(.custom-editor .ql-editor) { min-height: 200px; max-height: 600px; overflow-y: auto; color: #f9f9f9; background-color: #121212; } iframe { width: 100%; height: 315px; border: none; } .editPublicationPage { @apply w-full mx-auto p-8; } .title { @apply text-3xl font-semibold mb-6; } .form-wrapper { @apply space-y-8; label { @apply block text-lg font-medium text-white; } } </style>

``

@jxjj
Copy link

jxjj commented Aug 19, 2024

I ran into a similar issue using vue with refs, also described here: #4293

Changing to a plain variable resolved things for me.

//  ❌ doesn't work with Quill2 for me
const quillRef = ref<Quill | null>(null)

onMounted(() => {
  quillRef.value = new Quill(...)
});
// ✅  works with quill2
let quill: Quill | null = null

onMounted(() => {
   quill = new Quill(...)
})

@erodriguezg
Copy link
Author

thanks @jxjj , that worked
image

@ngd-b
Copy link

ngd-b commented Oct 28, 2024

thanks! that's good!

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

No branches or pull requests

3 participants