Linking a Kendo widget to an HtmlHelper component through JavaScript in MVC/Razor

I am currently working on integrating an MVC ListBoxFor control with a Kendo MultiSelectFor to bind and update data.

The goal is to have a list of users in the ListBox, and a list of available users in the MultiSelect box. When users are selected from the MultiSelect box and the add button is clicked, an Ajax call is made to update the users list server-side. The client-side JavaScript then updates the users and available users array object, keeping the controls up-to-date with the updated lists.

While I wish there was just one issue to tackle, each attempt seems to bring about different errors. So, let's focus on the latest problem:

Model:

public IEnumerable<UserInformation> Users { get; set; }
public IEnumerable<UserInformation> AvailableUsers { get; set; }

JavaScript ViewModel:

var viewModel = kendo.observable({
        availableUsersSelected: [],
        users: @(Html.Raw(Json.Encode(this.Model.Users))),
        availableUsers: @(Html.Raw(JsonConvert.SerializeObject(this.Model.AvailableUsers))),
        moveToUsers: function () {
            this.availableUsersSelected = this.get('availableUsersSelected');

            this.users.push(this.availableUsers);

            if (this.availableUsersSelected.length > 0) {
                var formAction = '@Url.Combine(Url.Content("~/"), ControllerActions.Groups.GroupDefault, ControllerActions.Groups.AddUser)';
                $.ajax({
                    url: formAction,
                    type: 'POST',
                    data: {
                        model: JSON.stringify(
                            {
                                groupId: $('#GroupId').val(),
                                users: this.availableUsersSelected
                            }
                    )
                    },
                    success: function (result) {
                        if (result) {
                            this.users.remove(this.availableUsersSelected);
                        }
                    }
                });
            }
        }
    });

MultiSelectFor control

@(Html.Kendo()
    .MultiSelectFor(u => u.AvailableUsers)
    .Placeholder("Please select")
    .BindTo(new SelectList(Model.AvailableUsers, "Id", "Name"))
    .HtmlAttributes(new { data_bind = "value: availableUsersSelected" })
)

ListBox control

@(Html.EditorLine(Language.Fields.Users, Html.ListBoxFor(u => u.Users, new SelectList(Model.Users, "Id", "Name"), new { @class = "form-control", data_bind = "source: users", data_value_field ="Id", data_text_field = "Name" })))

Add control

<img src="~/Content/images/up-arrow.jpg" alt="Move to users" width="30" data-bind="events: {click: moveToUsers}" />

In summary, while the Ajax calls and server-side updates are successful, I am encountering challenges with the client-side control binding.

The specific errors I'm facing include a syntax error with the comma on this line

users: @(Html.Raw(Json.Encode(this.Model.Users))),
, as well as a "ReferenceError: Id is not defined" when the moveToUsers function is called upon clicking the add button.

(Apologies for any frustration coming through in the question - this process has been quite challenging.)

Answer №1

After taking a moment to calm down and delving deeper into the documentation on data binding and observable arrays, I discovered that I had been making some crucial errors.

Upon refining my JavaScript ViewModel:

var viewModel = {
        availableUsersSelected: new kendo.data.ObservableArray([]),
        users: new kendo.data.ObservableArray(@(Html.Raw(Json.Encode(this.Model.Users)))),
        availableUsers: new kendo.data.ObservableArray(@(Html.Raw(Json.Encode(this.Model.AvailableUsers)))),
        moveToUsers: function () {
            if (viewModel.availableUsersSelected.length > 0) {
                var formAction = '@Url.Combine(Url.Content("~/"), ControllerActions.Groups.GroupDefault, ControllerActions.Groups.AddUser)';
                $.ajax({
                    url: formAction,
                    type: 'POST',
                    data: {
                        model: JSON.stringify(
                            {
                                groupId: $('#GroupId').val(),
                                users: viewModel.availableUsersSelected
                            }
                    )
                    },
                    success: function (result) {
                        if (result) {
                            removeFromAvailableUsers();
                        }
                        else
                            alert('add failed!');
                    },
                    failure: function () {
                        alert('ajax failed!');
                    }
                });
            }
        }
    };

function removeFromAvailableUsers() {
    for (var i = 0; i < viewModel.availableUsersSelected.length; ++i) {
        viewModel.users.push(viewModel.availableUsersSelected[i]);
        viewModel.availableUsers.remove(viewModel.availableUsersSelected[i]);
    }
    var ele = $('#AvailableUsers').data("kendoMultiSelect");
    ele.value("");
    ele.input.blur();
};

The key differences include declaring each array as an observable array within the main object instead of assuming "this" would encapsulate them. This simplifies referencing through the viewModel object.

In addition, following D_Learning's suggestion in the comments, I realized I had redundantly used two bindings for the MultiSelect control. Therefore, it was streamlined to:

    @(Html.Kendo()
        .MultiSelectFor(u => u.AvailableUsers)
        .Placeholder("Please select")
        .HtmlAttributes(new { data_bind = "source: availableUsers, value: availableUsersSelected", data_value_field = "Id", data_text_field = "Name" })
    )

(Note the absence of ".BindTo" property)

Overall, the MVC aspects remained consistent, and now everything functions flawlessly.

Answer №2

If you want to modify the content of the Kendo Multiselect, you can do so by using the DataSource. Here's an example of how to add data:

$("#AvailableUsers").data("kendoMultiSelect").dataSource.add({"text": "new Item", "value": 1000});

For more information on adding or removing items from a Multiselect (Kendo DataSource), check out: Kendo DataSource Adding Removing Items

Similarly, you can remove items from an HTML Listbox like this:

var selectedIndex = ListBox1.selectedIndex();
clearSelection();

if (selectedIndex != -1) {
    ListBox1.options.remove(selectedIndex);

To learn more about manipulating items in an HTML Listbox, visit: HTML Listbox Items Manipulation.

If you encounter any issues, please feel free to reach out.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Mastering the use of node cluster mode in conjunction with agenda cronjobs

Currently, I am utilizing nodejs and agenda to run cronjobs. With a total of 10 cronjobs in place, the process is taking longer as nodejs is single-threaded and they all run simultaneously. In an attempt to resolve this issue, I experimented with pm2 by e ...

Form that adjusts input fields according to the selected input value

I am in need of creating a dynamic web form where users can select a category and based on their selection, new input fields will appear. I believe this involves using JavaScript, but my searches on GitHub and Stack Overflow have not yielded a suitable sol ...

From Python Plotly to JavaScript Plotly - Leveraging the Power of

My primary goal is to avoid using JavaScript and instead focus on analytics. Is it possible for me to create Plotly graphs in Python (for example, in Jupyter notebooks) and then utilize the write_html function to seamlessly integrate them into fully deve ...

Utilizing HTML and JavaScript to Download Images from a Web Browser

I'm interested in adding a feature that allows users to save an image (svg) from a webpage onto their local machine, but I'm not sure how to go about doing this. I know it can be done with canvas, but I'm unsure about regular images. Here i ...

Not sure about the Fat Arrow (=>) function

Hey there, I've been diving into NextJs and came across this issue: This Module is Functional const GlobalStyles = () => ( <> <Global styles={css` body { color: #000000; } `} ...

Eliminate elements from an array within a promise

I am facing an issue with the currentBillCyclePath parameter in the following function. I need to use this parameter to filter out certain elements after executing the query. However, inside the while loop, the value of currentBillCyclePath is undefined. ...

Developing a server-side handler for jQuery file upload

I am currently working on integrating the blueimp jQuery-File-Upload component into my MVC application. Here is the code I have implemented so far: JavaScript: $('#fileupload').fileupload({ url: '@Url.Action("AddAttachment", "File")&a ...

Issue on WordPress where JQuery is undefined causing continuous refreshing on IPhone devices

My wordpress website is performing well in most browsers, including some mobile ones. However, when accessed on an IPhone, the homepage keeps refreshing in a continuous loop. Even after emulating an IPhone using Chrome developer tools, the issue persists. ...

Enhancing the theme using material-ui@next and typescript

While developing my theme using material-ui, I decided to introduce two new palette options that would offer a wider range of light and dark shades. To achieve this, I extended the Theme type with the necessary modifications: import {Theme} from "material ...

The action 'onDeleteClick' cannot be executed as the property is undefined

Why is the onDeleteClick function working on the first <div>, but returning undefined on the second one? I am able to access the reference of this, but when clicking, it shows "onDeleteClick of undefined". I am confused as to why the onDeleteClick f ...

Is it possible to upload a file using Angular and ASP.NET Web API Core?

I am encountering an issue with CORS policy while making requests. It works fine when the content-type is set to 'application/json'. However, when I try to upload a file using content-type 'multipart/form-data', I receive an error: XML ...

Do the vue/attribute-hyphenation default rule and vue/prop-name-casing conflict with each other?

I am currently working on a project using eslint-plugin-vue, where I have both child and parent components. The issue at hand is that the child component needs to pass a value into the parent component. // parent export default { name: 'recordDetail ...

Steps to create a toggle feature for the FAQ accordion

I am currently working on creating an interactive FAQ accordion with specific features in mind: 1- Only one question and answer visible at a time (I have achieved this) 2- When toggling the open question, it should close automatically (having trouble with ...

It appears that the JavaScript global dynamic variable is undefined as it changes from function to function, suggesting it might be

I'm encountering an issue with the way these two functions interact when used in onclick calls of elements. Due to external circumstances beyond my control, I need to keep track of when and how elements are hidden. Everything works perfectly as inten ...

The method WebKitBrowser.StringByEvaluatingJavaScriptFromString does not provide any output

After running all JavaScript, I need to retrieve the HTML content. However, I am facing an issue using WebKit.NET where the method WebKitBrowser.StringByEvaluatingJavaScriptFromString does not return anything, even with a simple alert(). When I try passi ...

Exploring the implementation of toggling functionality for nested children within <li> elements using jQuery

Unable to get the toggle function working on child nodes. Can someone assist me with this issue? $(document).ready(function() { $('label.tree-toggler').click(function() { $(this).parent().children('ul.tree').toggle(300); }); ...

How can you quickly navigate to the top of the page before clicking on a link in the same window/tab?

Could someone assist me with a coding issue I am facing? I would like to be able to go to the top of the page when clicking on a link and have the link open in the same tab. I attempted to implement this functionality using the following code, however, I ...

What happens when tabs are dynamically added on keypress?

I am encountering issues with this code snippet. $('body').on("keypress", ".message", function(e) { if ( e.keyCode == 13 && $(".message").val().length > 0 ) { input = $(".message"); // Check for join com ...

Maintain modifications in AngularJS modal even after closure

I have an HTML file with some AngularJS code for a modal window. <div ng-controller="ModalDemoCtrl"> <script type="text/ng-template" id="myModalContent.html"> <div class="modal-header"> <h3>I'm a modal!</h3> ...

Insert item at the end of the box and move all elements upwards

Hello! I'm experimenting with creating something using javascript's createElement method. My goal is to achieve an effect similar to this image: https://i.stack.imgur.com/itKUK.gif Currently, my code is functional, but the animation goes from to ...