Yêu cầu thg 10 2, 2023 9:02 SA 135 1 1
  • 135 1 1
+1

Xử lý expand quill-view-html trong angular

Chia sẻ
  • 135 1 1

Hiện tại em đang sử dụng quill-view-html để editor trong angular Em muốn có cái chức năng expand nội dụng thì xử lý như thế nào ạ

image.png

Hiện tại em sử dụng code như sau để hiển thị

<div *ngIf="traLoi" class="bg-gray-200 flex flex-col ">
    ...
    <div class="line-clamp-2 max-h-20" id="traLoi">
        <quill-view-html class="app-bg-gray" [content]="traLoi?.NOI_DUNG"></quill-view-html>
    </div>
    <div *ngIf="checkShowExpandedCTTL()" class="text-center absolute bottom-0 left-0 right-0 bg-gradient-to-b from-transparent  to-gray-300 h-18 ">
        <span class="content-between absolute bottom-0 left-0 right-0 hover:cursor-pointer ">Ấn vào đây để mở rộng</span>
    </div>
</div>

    checkShowExpandedCTTL(): boolean {
        const element: HTMLElement = document.getElementById( 'traLoi');
        const quillEditor: HTMLElement = element.querySelector('quill-view-html');
         return element.offsetHeight < quillEditor.offsetHeight;
    }
    

traLoi nó sẽ thay đổi khi ấn vào các button

Nhưng nó xuất hiện lỗiimage.png

thì xử lý làm sao ạ

1 CÂU TRẢ LỜI


Đã trả lời thg 10 2, 2023 2:46 CH
Đã được chấp nhận
+1

Lỗi expression changed after view has been checked error xảy ra ở code của e ở đoạn *ngIf, lỗi này xảy ra khi biểu thức bên trong ngif của e bị thay đổi khi Angular vừa thực hiện xong việc "check".

Khi dev ở local (development mode), Angular làm 1 việc giống với React đó là thực hiện "thêm" 1 lần "check" sau mỗi lần chạy Change Detection, nhằm đảm bảo là cái state e bind ko thay đổi, cụ thể là *ngIf="traLoi".

Khả năng cao là e đang thay đổi state traLoi ở trong ngOnChanges, ngAfterViewInit, hoặc là 1 số thao tác async chạy sau Change Detection. Cái này phải có code đoạn e set this.traLoi mới nói rõ được.

1 trong những cách fix phổ biến cho e đó là "wrap" đoạn e set this.traLoi vào setTimeout với 0 delay là được.

Ví dụ

setTimeout(() => {
  this.traLoi = true
}, 0)

hoặc e có thể dùng delay(0) nếu e đang dùng RxJS. Hoặc tốt hơn nữa nếu như e có thể move đoạn code kia từ ngAfterViewInit sang ngOnInit thì ko cần setTimeout hay delay gì cả (nếu e đang dùng ngAfterViewInit)

Chia sẻ
Avatar TMH @hoang55dd
thg 10 3, 2023 1:34 SA

this.traLoi nó được thay đổi khi ấn vào các item khác nhau ạ. Hiện tại nó có 2 loại action thay đổi đến nó

    ontTraLoiSelected(item) {
        this.traLoi= item;
        ...
    }
    resetTraLoiSelected() {
        this.traLoi= null;
    }

Lỗi chỉ xuất hiện khi diều kiện *ngIf="checkShowExpandedCTTL()" thay đổi giá trị ạ

Em thử setTimeout nhưng vẫn không được ạ

Avatar Mai Trung Đức @maitrungduc1410
thg 10 3, 2023 4:35 SA

@hoang55dd oh sorry e, hôm qua a ko nhìn thấy còn 1 cái ngIf bên dưới.

Sau khi xem code mới của e thì khả năng lỗi lại bị ở đây *ngIf="checkShowExpandedCTTL()" -> giá trị trả về của checkShowExpandedCTTL() thay đổi sau khi Angular vừa "check" xong template của e, như lỗi in ra thì tại thời điểm check là false nhưng về sau bị đổi thành true

tức là đoạn này return element.offsetHeight < quillEditor.offsetHeight; bị thay đổi

bởi vì e đang dùng cả cái method ở ngif nên method đó sẽ bị gọi rất nhiều lần, vì e cần nhớ là ở Angular, mỗi khi có thay đổi ở bất kì đâu trong app của e , thì Change Detection sẽ chạy lại cho toàn bộ application tree (mặc định, trừ khi e dùng OnPush), ý là cái method sẽ bị gọi đi gọi lại rất nhiều. e có thể đặt console.log ở trong đó để kiểm chứng.

Cách a khuyên e là, tạo 1 property mới cho component của e, ví dụ: showExpandedCTTL = false, ở template đoạn ngIf=checkShowExpandedCTTL() sửa thành ngIf="showExpandedCTTL"

method của e sửa thành:

checkShowExpandedCTTL(): boolean {
        const element: HTMLElement = document.getElementById( 'traLoi');
        const quillEditor: HTMLElement = element.querySelector('quill-view-html');
         this.showExpandedCTTL = element.offsetHeight < quillEditor.offsetHeight;
    }

rồi ở những chỗ nào e set this. traLoi thì sau đó e gọi thêm this.checkShowExpandedCTTL(), ví dụ:

ontTraLoiSelected(item) {
        this.traLoi= item;
        this.checkShowExpandedCTTL()
        ...
    }

Như này sẽ giảm đáng kể việc method checkShowExpandedCTTL bị gọi và sẽ fix đc lỗi

nếu sau khi làm như trên vẫn bị lỗi thì e lại wrap những chỗ gọi this.checkShowExpandedCTTL() trong setTimeout, lần này sẽ được thôi 😉

khi code, ngôn ngữ nào cũng vậy, hạn chế dùng tiếng việt nhé e, tập dùng tiếng Anh cho quen: ontTraLoiSelected, traLoi ---> onAnswerSelected, answer

Avatar TMH @hoang55dd
thg 10 3, 2023 7:09 SA

@maitrungduc1410 em fix được rồi ạ. Em cảm ơn anh câu trả lời và lời khuyên của a ♥️

Avatar Mai Trung Đức @maitrungduc1410
thg 10 3, 2023 7:38 SA

@hoang55dd okie e nhé

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí