Front-End

[Vue.js + Vuetify.js] Jodit 에디터 파일 업로드 기능 구현시 함수 또는 스크립트(method) 호출시 is not a function 오류가 발생할 때 처리하는 방법

Jodit 에디터 사용시 서버로 파일 업로드 기능을  사용하려면 별도의 추가 작업을 해야한다. 

파일 업로드시 formdata 형식으로 서버로 전달담으로 vue에서 파일업로드시 axios에서 formdata를 파라미터로 사용하는 것과 동일하게 보면 된다. 그럼으로 별도의 파라미터 작업은 할게 없다.

 

Jodit.make() 함수를 사용하여 기본 설정시 파일 업로드를 위해 uploader 속성을 사용하게 된다.

그렇게 하면 아래와 같이 업로드 버튼이 생성된다.


그런데 문제가 있다. uploader 속성 내부에서 vue 파일의 method 영역에 작성한 함수(스크립트)를 호출하면 is not a function이라는 오류가 발생하면서 찾을 수 없다.

파일 업로드 성공 후 isSuccess 콜백함수에서 이미지 파일인지 아닌지에 따라 insertImage를 사용할 것인지 아니면 insertHtml를 사용하여 파일링크를 만들 것인지 분기해야한다.

 

그런데 파일 구분하는 스크립트를 호출하지 못하는 것이다.

원인을 알 수 없어 2시간을 삽질했다. 공통으로 사용하는 baseCommon.js 스크립트에 작성된 함수도 호출할 수 없었다.

 

해결방법은 Jodit.make()함수를 사용하여 에디터 기본 설정시 uploader 선언하는 내부에 custom 함수를 선언하여 사용해야 접근됨을 확인하였다.

그리고 호출해서 사용할 때는 아래와 같이 사용하면 된다.

const isImage = this.options.myIsImage(fileNm);

this.option. 속성으로 접근 후 custom 함수를 호출해주면 성공!!!

 

joditEditor = Jodit.make(id, {
	zIndex: 0,
	height: this.height,
	toolbar: true,
	readonly: false,
	tabIndex: -1,
	disabled: false,
	toolbarButtonSize: 'large',
	// imageDefaultWidth: 100,
	// buttons: 'italic,bold,underline,strikethrough,eraser,ul,ol,font,fontsize,paragraph,classSpan,lineHeight,superscript,subscript,file,image,video,selectall',
	removeButtons: ['fullsize','about'],
	toolbarButtonSize: 'middle',
	autofocus: false,
	uploader: {
	  enableDragAndDropFileToEditor: true,
	  insertImageAsBase64URI: false,
	  url: '/upload/uploadToServer.do',
	  baseurl: 'http://localhost:8080/',
	  uploader: { filesVariableName: 'filePath' },
	  format: 'json',
	  method: 'POST',
	  pathVariableName: 'path',
	  prepareData: function (formdata) {
		console.log(formdata);
		//formdata.append('id', 24); // $_POST['id'] on server
		return formdata;
	  },
	  myIsImage: function (fileNm) {
		if (fileNm !== undefined) {
		  const reg = /(.*?).(jpg|jpeg|png|gif|bmp|svg|ico)$/;
		  if (fileNm.match(reg)) {
			return true;
		  }
		  return false;
		} 
		return false;
	  },
	  myGetFileExt: function (fileNm) {
		if (fileNm !== undefined) {
		  const fileLen = fileNm.length;
		  const lastDot = fileNm.lastIndexOf('.');
		  return fileNm.substring(lastDot + 1, fileLen).toLowerCase();
		}
		return '';
	  },
	  isSuccess: function (resp) {
      	//json타입으로 array 데이터를 리턴 받아서 처리할 때 
		if (resp.fileKey && resp.fileKey.length) {
		  resp.fileKey.forEach((item, idx) => {
			const fileNm = resp.fileNm[idx];
			if (this.options.myIsImage(fileNm)) {
			  this.jodit.selection.insertImage(this.options.baseurl + resp.filePath[idx]);
			} else {
			  const html = `<a @click="${this.options.baseurl + resp.filePath[idx]}">${fileNm}</a>`;
			  // this.jodit.selection.insertHTML(html, null, 3000);
			  this.jodit.selection.insertHTML(html);
			}
		  });
		}
		return !resp.error;
	  },
	  defaultHandlerSuccess: function() {
	  },
	  defaultHandlerError: function (resp) {
		this.events.fire('errorPopap', [this.options.uploader.getMsg(resp)]);
	  },
	  error: function (e) {
		console.log('error', e);
		// this.j.e.fire('errorMessage', e.message, 'error', 4000);
	  },
	},
  });

 

[연관자료]

 

Leave a Reply

error: Content is protected !!