1

I have written a reusable component in Angular 2 to display the Summernote WYSIWYG editor in my application. That component accepts 3 input parameters which are being set as attributes for a rendered textarea as id, name and last one used as the body. My problem is that within this component I am initializing the Summernote plugin and creating the editor. Here, I do not want to hard code the selector name and want the dynamic values that the component received as the input parameters to the component. Relevant code is as follows.

import {Component, ElementRef, OnInit, EventEmitter, Input, Output, Inject, ComponentRef} from '@angular/core';
import {Http} from '@angular/http';

declare var $: any;

@Component({
    selector: 'editor',
    template: `<textarea id="{{eid}}" name="{{ename}}" class="form-control">{{body}}</textarea>`
})

export class EditorComponent {

    @Input() body: string;
    @Input() eid: string;
    @Input() ename: string;
    @Output() onContentChanged: EventEmitter<any>;

    constructor(){}

    ngAfterViewInit()
    {
        $(document).on("pageLoaded", function (){
            console.log("pageLoaded");

                $("#body").summernote({
                    height: '200px',
                    callbacks: {
                        onChange: function(contents, $editable) {
                            $("#body").val(contents);
                        }
                    }
                });

        });
    }
}

Here, you can see that I have used $("#body") twice inside the ngAfterViewInit block. I want this to be replaced by the eid variable. I have tried {{eid}} but it doesn't work and throws the following error in browser console.

EXCEPTION: Syntax error, unrecognized expression: #{{eid}}

this.eid can't be used here either since we're inside the javascript method and not typescript.

I'm using this component in my other view file as a directive.

<editor [body]="page.body" eid="body" ename="body"></editor>

The template block in component is set properly with dynamic values. Only the javascript part is my issue.

Is there any other way I'm missing here?

P.S. So far it works great. I just want to make the initialization fully dynamic, so that I can use it anywhere with different IDs.

4
  • Have you tried the old method of binding the context into the function so that you can access this and all its variables? Commented Oct 13, 2016 at 14:36
  • @Katana24 Can you please be more specific and provide an example please? Commented Oct 13, 2016 at 15:05
  • Have a look at this article developer.mozilla.org/en/docs/Web/JavaScript/Reference/… - Also - why are using Jquery in there? Commented Oct 13, 2016 at 15:16
  • your reference article is something completely off the topic. I'm talking about Typescript vs Javascript scopes here. I'm using jQuery here because Angular 2 final version has just released and the plugin I'm using is not ported to Angular 2 yet. So, I have to live with it and use the jQuery version. Commented Oct 13, 2016 at 15:40

1 Answer 1

5

You can try using arrow functions instead of function to keep the same context.

  $(document).on("pageLoaded", () => {
            console.log("pageLoaded");

                $(this.eid).summernote({
                    height: '200px',
                    callbacks: {
                        onChange: (contents, $editable) => {
                            $(this.eid).val(contents);
                        }
                    }
                });

        });
    }
Sign up to request clarification or add additional context in comments.

2 Comments

It's a lovely answer. I didn't know we could mix Typescript and Javascript using arrow functions to keep the same context. It did partially solve my issue and gave me the value I needed but I'm also having tons of exceptions now. Major one says repeatedly Zone already loaded. And my editor is not initialized on the textarea but on the whole page. i.e. whole page is inside the Editor.
Alright, my bad... actually my this.eid variable contained the text "body" so $(this.eid) became $("body") on runtime. Which made it initialize on the body element. I just changed it to $("#" + this.eid) and everything is great now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.