susmita rai
susmita rai

Reputation: 39

How can I add validation using ql-image on p-editor in angular?

Can anyone help me how to call function on input tag which will be created from ql-image of p-editor. I want to limit the size of the image on that function. But I am unable to call the function in that input tag.

Below is the section of p-editor code I am using for uploading the image.

<p-editor #pEditor required class="pEditor">
  <p-header>
    <span class="ql-formats">
     <button class="ql-clean" aria-label="Remove Styles" tabindex="-1"></button>
     <button class="ql-image" aria-label="Insert Image"  tabindex="-1"></button>
    </span>
  </p-header>
 </p-editor>

The input tag is shown in the source. How can I add function to this tag?

enter image description here

Upvotes: 1

Views: 1843

Answers (2)

Aleš Doganoc
Aleš Doganoc

Reputation: 12052

The primeng editor uses on the inside the Qill rich text editor. To do what you want you actually need to extend the Quill editor. They offer extensibility and you can override the actions that happen when you press the toolbar buttons. In this case you need to add your own custom toolbar handler for the image action. To get the Quill editor from the primeng editor there is a provided method getQuill check the primeng Editor documentation for more details. You can get the editor in the ngAfterViewinit lifecycle event hook and then attach the custom handler to add your image processing. To implement the handler you need to duplicate all the code that creates the input and downloads the file. Unfortunately it is not so simple but you can then do anything you want inside it. I have copied it from the original code in Quill editor and just added the size handling.

Here is my sample implementation.

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
  public title = 'CodeSandbox';
  public text: string;
  @ViewChild(Editor) editor: Editor;

  public ngAfterViewInit() {
    const quill = this.editor.getQuill();
    const toolbar = quill.getModule('toolbar');
    toolbar.addHandler('image', function () {
      const fileInput = toolbar.container.querySelector(
        'input.ql-image[type=file]'
      );
      if (fileInput == null) {
        fileInput = document.createElement('input');
        fileInput.setAttribute('type', 'file');
        fileInput.setAttribute(
          'accept',
          'image/png, image/gif, image/jpeg, image/bmp, image/x-icon'
        );
        fileInput.classList.add('ql-image');
        fileInput.addEventListener('change', function () {
          if (fileInput.files != null && fileInput.files[0] != null) {
            if (fileInput.files[0].size > 102400) {
              alert('image to big it neeeds to be les than 100kb');
            } else {
              const reader = new FileReader();
              reader.onload = function (e) {
                const range = quill.getSelection(true);
                quill.updateContents(
                  new Delta().retain(range.index).delete(range.length).insert({
                    image: e.target.result
                  }),
                  'user'
                );
                quill.setSelection(range.index + 1, 'silent');
                fileInput.value = '';
              };
              reader.readAsDataURL(fileInput.files[0]);
            }
          }
        });
        toolbar.container.appendChild(fileInput);
      }
      fileInput.click();
    });
  }
}

And also the html template.

<p-editor [(ngModel)]="text" [style]="{'height':'320px'}"></p-editor>

To see it working you can check the CodeSandbox with the fully implemented sample.

Upvotes: 2

Shashan Sooriyahetti
Shashan Sooriyahetti

Reputation: 878

Bit complicated but can do,

Note: it is better if you can add unique ids

//collection of class tag elements
console.log(document.getElementsByClassName("ql-image"));

// assign it to a variable
let elementsCollection = document.getElementsByClassName("ql-image");

//convert it to an array
let tags = Array.prototype.slice.call(elementsCollection, 0) as Array<any>;

//map and get the input element
tags.map(e => {
  if (e.tagName === "INPUT") {


   //one way when input changes
      e.addEventListener('change', (event) => {
      let newFile = e.files[0];
      if (!newFile) {
        console.log("please select a file");
      } else {
        let file = newFile;
        console.log(
          "File " + file.name + " is " + file.size / 10 ** 6 + " mb in size"
        );
      }
    });


    //assumed you can add id to insert image button and when uploading
    document.getElementById("btnLoad").addEventListener("click", () => {
      let newFile = e.files[0];
      if (!newFile) {
        console.log("please select a file");
      } else { 
        let file = newFile;
        console.log(
          "File " + file.name + " is " + file.size / 10 ** 6 + " mb in size"
        );
        //add your filesize logic here
      }
    });
  }
});



//HTML I used 
<button id="btnLoad" class="ql-image" aria-label="Insert Image" 
tabindex="-1">Insert Image</button>
   
<input class="ql-image" type="file">

stackbliz example

Hope this is enough to get you going :) enjoy! Please note that inside the map I have explained two ways to do this

Upvotes: 0

Related Questions