Can ElementRef property be set to a javascript interop return value in Blazor?

asp.net-core blazor c#

Question

I am tinkering with CodeMirror on a textarea element. I am using javascript interop to accomplish this and it works fine when applying the code mirror. However my intention is to return that codemirror element and store that in another elementref.

Blazor.registerFunction('BlazorExt.CodeMirrorSetupExt', (element) =>
{
    return CodeMirror.fromTextArea(element,
    {
        mode: 'application/ld+json',
        matchBrackets: true,
        autoCloseBrackets: true,
        indentWithTabs: true,
        lineNumbers: true,
        autofocus: true,
        styleActiveLine: true,
        readOnly: false,
        autoCloseBrackets: true,
        foldGutter: true,
        height: 'auto',
        width: 'auto',
        gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter']
    });
});

        public static ElementRef CodeMirrorSetupExt(this ElementRef elementRef)
    {
        var result = RegisteredFunction.Invoke<ElementRef>("BlazorExt.CodeMirrorSetupExt", elementRef);
        return result;
    }

In my component:

//in my html i have a textarea with ref of TextArea

ElementRef CodeMirror;
ElementRef TextArea;

protected override void OnAfterRender()
{

    CodeMirror = TextArea.CodeMirrorSetupExt();
}

Ideally after this point I should be able to update my codemirror ref using its functions like so.

    Blazor.registerFunction('BlazorExt.CodeMirrorUpdateExt', (element, Value) =>
{
    element.getDoc().setValue(Value);
});

        public static void CodeMirrorUpdateExt(this ElementRef elementRef, string Value)
    {
        var args = new object[] { elementRef, Value };
        RegisteredFunction.Invoke<object>("BlazorExt.CodeMirrorUpdateExt", args);
    }

In the component again I should be able to update the codemirror like so:

CodeMirror.CodeMirrorUpdateExt("somedata");

However I get an exception: Microsoft.AspNetCore.Blazor.Browser.Interop.JavaScriptException: Cannot read property 'getDoc' of null

Is what I am trying to accomplish outside of what is possible or is passing a codemirror javascript object into an elementref not possible?

1
2
5/14/2018 10:45:37 PM

Accepted Answer

No, this is not (yet) possible. See here

What you can do, is register your javascript object globally and use that reference for eventual second uses. Like so:

Blazor.registerFunction('BlazorExt.CodeMirrorSetupExt', (element) =>
{
  window.mybject = CodeMirror.fromTextArea(element,
  {
     mode: 'application/ld+json',
     matchBrackets: true,
     autoCloseBrackets: true,
     indentWithTabs: true,
     lineNumbers: true,
     autofocus: true,
     styleActiveLine: true,
     readOnly: false,
     autoCloseBrackets: true,
     foldGutter: true,
     height: 'auto',
     width: 'auto',
     gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter']
   });
   return true;
 });

public static void CodeMirrorSetupExt(this ElementRef elementRef)
{
    RegisteredFunction.Invoke<bool>("BlazorExt.CodeMirrorSetupExt", elementRef);
}

And then:

  Blazor.registerFunction('BlazorExt.CodeMirrorUpdateExt', (element, Value)=>{
    window.myObject.getDoc().setValue(Value);
});

Of course you can make this nicer with an array and a key as reference.

0
5/15/2018 5:15:56 AM

Popular Answer

I extended @Flores answer. Instead of making a global array of all your javascript objects, just stash the new value inside a javascript DOM object you already have an elementReference to.

window.hintCodeMirrorIntegration = {
    initialize: function(element, markupMode) {
        element.codeMirrorLink = CodeMirror.fromTextArea(element,
           {
            ...
            });
        return 0;
    },

    getCode: function(element) {
        return element.codeMirrorLink.getValue();
    }

}

On the c# side I pass in the ElementReference to the text area. I hang on to that reference, and when I want the code ouf of the CodeMirror object, I find it inside the TextArea that I already have a reference to. This also nicely ties the lifetime of the CodeMirror object to the text area it is shadowing.

 private ElementReference textToEdit;
 protected override Task OnAfterRenderAsync()
  {
      return javascriptRuntime.InvokeAsync<int>("hintCodeMirrorIntegration.initialize", textToEdit,
          Context.CurrentAsset.MimeType);
  }

private async Task Save()
{
    var code = await javascriptRuntime.InvokeAsync<string>("hintCodeMirrorIntegration.getCode", textToEdit);
    //... save the result in the database
}


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow