Refreshing string attribute (loaded from database) within prism.js textarea

195 Views Asked by At

I want to display a string, which I've loaded from my database, within my prism.js syntax highlighting textarea. I'm really new to HTML and JavaScript/TypeScript.

    <form [formGroup]="form">
                <div class="code-container line-numbers">
                  <textarea
                    #textArea
                    class="text-area-code-editor"
                    formControlName="content"
                    spellcheck="false"
                  ></textarea>
                  <pre
                    aria-hidden="true"
                    class="pre line-numbers"
                    #pre
                  ><code [ngClass]="['code', 'language-' + codeType]" #codeContent>{{currentCode}}</code>
                  </pre>
                </div>
              </form>

The right string for currentCode is existing within the Components attribute, but how can I trigger the textarea to display the new loaded one?

export class DisplaySourcecodeComponent implements OnInit, AfterViewChecked, AfterViewInit, OnDestroy {
  codeList = [];
  currentCode = "";
  nodesAndEdges = "";
  nodes : any;
  constructor(private data_service: DataService, private api_service: ApiService, private prismService: PrismService, private fb: FormBuilder,
    private renderer: Renderer2 ) { }


  @ViewChild('textArea', { static: true })
  textArea!: ElementRef;
  @ViewChild('codeContent', { static: true })
  codeContent!: ElementRef;
  @ViewChild('pre', { static: true })
  pre!: ElementRef;

  sub!: Subscription;
  highlighted = false;
  codeType = 'java';
  form = this.fb.group({
    content: ''
  });

  get contentControl() {
    return this.form.get('content');
  }


  ngOnInit(): void {
    this.listenForm();
    this.synchronizeScroll();
  }

  ngAfterViewInit() {
    this.prismService.highlightAll();
  }

  ngAfterViewChecked() {
    if (this.highlighted) {
      this.prismService.highlightAll();
      this.highlighted = false;
    }
  }

  ngOnDestroy() {
    this.sub?.unsubscribe();
  }


  private listenForm() {
    this.sub = this.form.valueChanges.subscribe((val) => {
      const modifiedContent = this.prismService.convertHtmlIntoString(val.content);

      this.renderer.setProperty(this.codeContent.nativeElement, 'innerHTML', modifiedContent);
      //this.currentCode = val.content;
      console.log("listenForm: " + this.currentCode)
      this.highlighted = true;
    });
  }


  private synchronizeScroll() {
    const localSub  = fromEvent(this.textArea.nativeElement, 'scroll').subscribe(() => {
      const toTop = this.textArea.nativeElement.scrollTop;
      const toLeft = this.textArea.nativeElement.scrollLeft;

      this.renderer.setProperty(this.pre.nativeElement, 'scrollTop', toTop);
      this.renderer.setProperty(this.pre.nativeElement, 'scrollLeft', toLeft + 0.2);
    });

    this.sub.add(localSub);
  }

  displaySourceCode(item : any): void {
    this.currentCode = item.code;
    //console.log("currentCode: " + this.currentCode);
  }

  loadSourceCodes() : void {
    this.codeList = [];
    this.api_service.getSourceCodes().subscribe(data => {
      for(let item of data) {
        this.codeList.push(item);
      }
    })
  }
}
1

There are 1 best solutions below

0
Kristen On

I had this problem today and I found this article useful

https://schier.co/blog/how-to-re-run-prismjs-on-ajax-content

highlightAll() can be used to force Prism to rerun on the current page, use highlightElement() to selectively highlight elements and avoid rescanning the entire DOM

// Say you have a code block like this

  <pre>
    <code id="some-code" class="language-javascript">
      // This is some random code
      var foo = "bar"
    </code>
  </pre>


// Be sure to select the inner <code> and not the <pre>

// Using plain Javascript
var block = document.getElementById('some-code')
Prism.highlightElement(block);

// Using JQuery
Prism.highlightElement($('#some-code')[0]);