将 Blazor 对象引用传递给 Telerik Chat 控件

问题描述 投票:0回答:1

我已阅读 Microsoft 的有关从 Blazor 调用 JavaScript 的文档。我访问过 Telerik 网站并搜索了他们的文档和论坛。我已经做了很多搜索引擎查询。我搜索过,发现类似的问题并不能完全回答我的问题。

具体来说,我希望作为传递给

kendo.Class.extend
的对象属性的 JavaScript 代码能够调用 Blazor 组件实例方法。

我不想做的是调用静态方法 - 我可以让它工作,但这不是我想要的。我不想在脚本标记中调用任意方法,因为我有使用具有特定语法的 Telerik Chat 控件的特定场景。

再次强调,如果您向我推荐另一个问题或向我显示链接,请确保它针对我的情况。

此方法的背景是 Telerik 没有 Blazor 聊天控件。因此,根据 Telerik 的建议,我需要在 Blazor 组件和 Kendo jQuery Chat 小部件之间进行通信。

这里的代码与如何编写 jQuery 部分的 Telerik 示例类似:

// MyChatComponent.razor.js

var chat = $("#chat").kendoChat({
    post: function (args) {
        agent.postMessage(args);
    }
}).data("kendoChat");

window.ChatAgent = kendo.Class.extend({
    init: function (chat, dotnet) {
        this.chat = chat;
        this.dotnet = dotnet;

        console.log('dotneti', dotnet);
    },
    postMessage: function (args) {
        var chat = this.chat;

        this.dotnet.invokeMethodAsync('MyChatComponent', 'AskAsync', args.text)
            .then(data => {
                chat.renderMessage({
                    type: "text",
                    text: data,
                    timestamp: new Date()
                }, {
                    name: "Generellem"
                });
            });
    }
});

var agent = new ChatAgent(chat);

agent.chat.renderMessage({
    type: "text",
    text: "Hi, How can I help today?",
    timestamp: new Date()
}, {
    name: "Generellem"
});

我所做的修改是将

dotnet
参数添加到
init
对象中的
kendo.Class.extend
函数中。再往下,在
postMessage
函数中,我使用
dotnet
实例变量来调用
invokeMethodAsync
。这不起作用 -
console.log
函数中的
init
打印出
dotnet
undefined

问题之一是我不知道将

dotnet
放在哪里才能拥有正确的实例引用。这将我带到了组件,这是我希望上面的代码接收的实例:

// MyChatComponent.razor

@page "/chat"
@rendermode InteractiveServer

@inject IJSRuntime JS

<h3>Chat</h3>

<div id="chat"></div>

@code {
    CancellationTokenSource cancelTokenSource = new();
    DotNetObjectReference<Chat>? objRef;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            objRef = DotNetObjectReference.Create(this);

            await JS.InvokeAsync<IJSObjectReference>(
            "import", "./Components/Pages/Chat.razor.js", objRef);
        }
    }

    [JSInvokable]
    public async Task<string> AskAsync(string message)
    {
        return await Task.FromResult(message);
    }
}

这里有一些有趣的项目。第一个是在

OnAfterRenderAsync
中,我调用
DotNetObjectReference.Create(this)
来获取当前对象的实例,如
objRef
。我想将
objRef
传递给 JavaScript 代码,以便我可以调用
AskAsync
实例方法。

AskAsync
内部,我添加了
objRef
作为
InvokeAsync
的第三个参数。我不知道这样做是否正确,但我尝试过。

总而言之,我想将

objRef
从 C# 代码传递到 JavaScript 代码,以便 JavaScript 代码在调用
AskAsync
时拥有对组件实例的引用。

javascript c# kendo-ui blazor telerik
1个回答
0
投票

这是我正在使用的解决方法,尽管感觉它缺乏优雅。本质上,我调用了 JS 函数来显式设置对象引用,而不是试图弄清楚如何在导入过程中传递参数。这是更新后的 JS 代码:

// MyChatComponent.razor.js

var chat = $("#chat").kendoChat({
    post: function (args) {
        agent.postMessage(args);
    }
}).data("kendoChat");

window.ChatAgent = kendo.Class.extend({
    init: function (chat) {
        this.chat = chat;
    },
    postMessage: function (args) {
        var chat = this.chat;

        this.dotnet.invokeMethodAsync('MyChatComponent', 'AskAsync', args.text)
            .then(data => {
                chat.renderMessage({
                    type: "text",
                    text: data,
                    timestamp: new Date()
                }, {
                    name: "Generellem"
                });
            });
    }
});

var agent = new ChatAgent(chat);

agent.chat.renderMessage({
    type: "text",
    text: "Hi, How can I help today?",
    timestamp: new Date()
}, {
    name: "Generellem"
});

var dotnet = {};

export function setDotnetInstance(objRef) {
    dotnet = objRef;
};

我从

dotnet
中删除了
kendo.Class.extend.init
参数。然后,我在文件末尾创建了一个对象变量
dotnet
。我还添加了
setDotnetInstance
函数导出,以引用 Blazor 组件来设置
dotnet
变量。

在 Blazor 组件中,我在

setDotnetInstance
中省略了
OnAfterRenderAsync
,如下所示:

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            objRef = DotNetObjectReference.Create(this);

            IJSObjectReference module = await JS.InvokeAsync<IJSObjectReference>(
                "import", "./Components/Pages/Chat.razor.js");
            await module.InvokeVoidAsync("setDotnetInstance", objRef);
        }
    }

改变是乘坐

IJSObjectReference
module
,从
JS.InvokeAsync
返回来用
setDotnetInstance
打电话给
InvokeVoidAsync

如果我找到更好的方法来做到这一点,我会更新这个答案。

© www.soinside.com 2019 - 2024. All rights reserved.