This is a migrated thread and some comments may be shown as answers.

"Add new" when item not available in list

11 Answers 506 Views
MultiSelect
This is a migrated thread and some comments may be shown as answers.
Nicklas
Top achievements
Rank 1
Nicklas asked on 05 Jul 2013, 10:19 AM
I came across this thread on the same issue, but without the use of server wrappers, which in my mind sort of complicates what I'm trying to accomplish. It led me to this example at JS Bin, but I can't seem to implement this in my existing code. Do you guys have any suggestions in regards to approaching this particular 'problem'?

Here's what I have today:
<div class="span3">
    @(Html.Kendo().MultiSelect()
      .Name("tags")
      .Placeholder("No tags selected for this unit")
      .BindTo(new SelectList(Model.TagsAvailable))
      .Events(e => e
                .Select("select")
                .Change("change"))
      .Value(Model.TagsSelected.ToArray())
      )
</div>
 
<script>
    function select(e) {
        var dataItem = this.dataSource.view()[e.item.index()];
        var param = dataItem.Text;
        var url = '@Url.Content("~/UnitDetails/TagUnit/" + Model.UnitId)';
 
        $.ajax({
            url: url,
            data: { selectedItem: param },
            type: 'GET',
            dataType: 'json',
            success: function (data) {
                
            },
            error: function () {
                
            }
        });
    };
 
    function change(e) {
        var dataItem = this;
        var param = dataItem.element.context.innerText;
        var url = '@Url.Content("~/UnitDetails/UnTagUnit/" + Model.UnitId)';
 
        $.ajax({
            url: url,
            data: { selectedItem: param },
            type: 'GET',
            dataType: 'json',
            success: function (data) {
                
            },
            error: function () {

            }
        });
    };
</script>
This is before I start mixing the code from the example I referenced earlier. Chose to remove it, because it just clutters my code anyway, in addition to not working. Hope you guys can help!

11 Answers, 1 is accepted

Sort by
0
Daniel
Telerik team
answered on 09 Jul 2013, 09:49 AM
Hello,

What is the needed functionality in your scenario? Could you provide a little more detailed information about it? What should happen in the change and in the select event? What happens when using the approach demonstrated in the jsBin? At least when I tested the suggested solution with the wrappers, the add functionality was working as expected. I attached my test project to this thread.

Regards,
Daniel
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Nicklas
Top achievements
Rank 1
answered on 10 Jul 2013, 01:36 PM
Thank you! That seems to work! However, as you can see from my code I have some more going on when the change-event is fired. I do an ajax call in order to store the changes done in the multiselect, immideately. 

My code seems to interfere with the one you suggested, causing the change event not to work properly. As the change event also picks up when "deleting" a tag, I need to do that in the same method.

function change(e) {
    var changedItem = this;
    var param = changedItem.element.context.innerText;
    var url = '@Url.Content("~/UnitDetails/UnTagUnit/" + Model.ViewUnitContract.Id)';
     
    var value = this.value().slice(0);
    var dataitems = this.dataSource.data();
    var newtag = "";
     
    for (var i = 0; i < dataitems.length; i++) {
        var dataItem = dataitems[i];
 
        if (dataItem.Text.substring(0, "Add new tag: ".length) === "Add new tag: ") {
            newtag = dataItem.Text.replace("Add new tag: ", "");
            this.dataSource.remove(dataItem);
        }
    }
 
    this.dataSource.add({ Value: newtag, Text: newtag });
 
    if (newtag) {
        this.dataSource.filter({});
        if (this.value().length == 1) {
            this.value(newtag);
        }
        else {
            value.push(newtag);
            console.log(value);
            this.value(value);
        }
    }
 
    $.ajax({
        url: url,
        data: { selectedItem: param },
        type: 'GET',
        dataType: 'json',
        success: function (data) {
            
        },
        error: function () {
            
        }
    });
}
Any suggestion on how I can make these two work 'in harmony' ? My old code is the three first variables as well as the $.ajax part at the bottom.
0
Daniel
Telerik team
answered on 12 Jul 2013, 09:30 AM
Hello again,

There does not seem to be anything in the additional code that would interfere with this functionality and when I tested it on my side it was working as expected. I attached the sample project modified to use the provided code. Let me know if it works as expected on your side or if I am missing something.

Regards,
Daniel
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Linus
Top achievements
Rank 1
answered on 28 Jan 2014, 08:27 AM
As a contribution to this (rather old) post I would like to provide a enhanced solution of MultiSelectAddItem.
It filters out the already existing items.
It uses another item class (IdNameItem) which fits better with database entries since it offers an Id property for the associated item id Db.
IMPORTANT: Please note that you have to copy in \bin and \script directory of the former MultiSelectAddItem project since I am not alowed to upload more than 2MB...
0
Alex
Top achievements
Rank 2
answered on 03 Oct 2014, 08:20 AM
I know this is an old post but I'm trying to achieve this too.

I've followed Daniels sample code and it works great for a local datasource, but if you use a remote data source it doesn't seem to work.

How would we have to amend the javascript to make this work with a remote datasource?
0
Daniel
Telerik team
answered on 07 Oct 2014, 12:14 PM
Hello Alex,

Could you provide the code that you are currently using so I can check the exact setup?

Regards,
Daniel
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Alex
Top achievements
Rank 2
answered on 11 Oct 2014, 02:26 AM
Hi Daniel,

I'm using the same code as above:

@(Html.Kendo().MultiSelect()
    .Name("tags")
    .Animation(false)   
    .Filter(FilterType.Contains)
    .DataSource(ds=>ds.Read("ListItemTest", "Test"))
    .DataValueField("value")
    .DataTextField("text")
    .Events(e=> e.Change("change").DataBound("dataBound"))
)
 
<script>
 
    function change() {
        var value = this.value().slice(0);
        var dataitems = this.dataSource.data();
        var newtag = "";
 
        for (var i = 0; i < dataitems.length; i++) {
            var dataItem = dataitems[i];
 
            if (dataItem.Text.substring(0, "Add new tag: ".length) === "Add new tag: ") {
                newtag = dataItem.Text.replace("Add new tag: ", "");
                this.dataSource.remove(dataItem);
            }
        }
 
        this.dataSource.add({ Value: newtag, Text: newtag });
 
        if (newtag) {
            this.dataSource.filter({});
            if (this.value().length == 1) {
                this.value(newtag);
            }
            else {
                value.push(newtag);
                console.log(value);
                this.value(value);
            }
        }
    }
    var newitemtext;
    function dataBound() {
 
        if ((newitemtext || this._prev) && newitemtext != this._prev) {
            newitemtext = this._prev;
 
            var dataitems = this.dataSource.data();
 
            var isfound = false;
            for (var i = 0; i < dataitems.length; i++) {
                var dataItem = dataitems[i];
 
                if (dataItem.Value != dataItem.Text) {
                    dataItem.Text = "Add new tag: " + newitemtext;
                    this.refresh();
                    isfound = true;
                }
            }
            if (!isfound) {
                this.dataSource.add({ Text: "Add new tag: " + newitemtext, Value: newitemtext });
                this.refresh();
            }
            this.search();
            this.open();
        }
    }
</script>


However this object seems to be null:

var dataitems = this.dataSource.data();


And I think that's why it doesn't work. However, if I change to this:

@(Html.Kendo().MultiSelect()
    .Name("tags")
    .Animation(false)   
    .Filter(FilterType.Contains)
    .BindTo(new List<SelectListItem>()
    {
        new SelectListItem() {
        Text = "Tag1", Value ="Tag1"
        },
        new SelectListItem() {
        Text = "Tag2", Value ="Tag2"
        },
        new SelectListItem() {
        Text = "Tag3", Value ="Tag3"
        }
    })
    .Events(e=> e.Change("change").DataBound("dataBound"))
)


It does work. Any ideas how to get this to work with the remote data source?

Thanks.
0
Daniel
Telerik team
answered on 15 Oct 2014, 07:32 AM
Hello again Alex,

Loading the data via Ajax should not make a difference but the dataTextField and dataValueField seems to be different
.DataValueField("value")
.DataTextField("text")
so the fields used in the handlers should be changed:
function change() {
    var value = this.value().slice(0);
    var dataitems = this.dataSource.data();
    var newtag = "";
 
    for (var i = 0; i < dataitems.length; i++) {
        var dataItem = dataitems[i];
 
        if (dataItem.text.substring(0, "Add new tag: ".length) === "Add new tag: ") {
            newtag = dataItem.text.replace("Add new tag: ", "");
            this.dataSource.remove(dataItem);
        }
    }
 
    this.dataSource.add({ value: newtag, text: newtag });
 
    if (newtag) {
        this.dataSource.filter({});
        if (this.value().length == 1) {
            this.value(newtag);
        } else {
            value.push(newtag);
            this.value(value);
        }
    }
}
var newitemtext;
function dataBound() {
 
    if ((newitemtext || this._prev) && newitemtext != this._prev) {
        newitemtext = this._prev;
 
        var dataitems = this.dataSource.data();
 
        var isfound = false;
        for (var i = 0; i < dataitems.length; i++) {
            var dataItem = dataitems[i];
 
            if (dataItem.value != dataItem.text) {
                dataItem.text = "Add new tag: " + newitemtext;
                this.refresh();
                isfound = true;
            }
        }
        if (!isfound) {
            this.dataSource.add({ text: "Add new tag: " + newitemtext, value: newitemtext });
            this.refresh();
        }
        this.search();
        this.open();
    }
}



Regards,
Daniel
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
JP
Top achievements
Rank 1
answered on 11 Mar 2015, 01:38 PM
Hi, 
I've tried running this zip file, but it can only add 3 items, any idea?
0
Marco
Top achievements
Rank 1
answered on 16 Jun 2015, 07:09 AM

Hi,

I'm also having problems with the code provided by Daniel.

After adding a second new item to the multiselect, the whole input field is blank.

Isn't there a native support for adding new items to a multiselect? The javascript solution seems to be a workaround.

 Best Regards

0
Daniel
Telerik team
answered on 18 Jun 2015, 01:30 PM
Hello,

The multiselect does not currently support this feature. This was previously requested. You can vote for it and follow its progress on this page.

Regards,
Daniel
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Tags
MultiSelect
Asked by
Nicklas
Top achievements
Rank 1
Answers by
Daniel
Telerik team
Nicklas
Top achievements
Rank 1
Linus
Top achievements
Rank 1
Alex
Top achievements
Rank 2
JP
Top achievements
Rank 1
Marco
Top achievements
Rank 1
Share this question
or