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

kendo.stringify creating weird json with drop downs and combos

10 Answers 60 Views
MVVM
This is a migrated thread and some comments may be shown as answers.
James
Top achievements
Rank 1
James asked on 16 May 2012, 09:19 PM
[{"FirstName":"James","LastOrCompanyName":"Hancock","MiddleName":"Robert","Suffix":{"value":"Sr.","text":"Sr."},"Salutation":"Mr.","Individual":false,"UserName":null,"DateOfBirth":null,"PublicSecurityPermissionID":null,"Sex":0,"BloodType":0,"WebSiteTheme":null,"PublicDescription":null,"ID":"545e6d6e-3bac-440f-86bb-5fb575e5ce68"}]

Note that the Suffix is value/text instead of just the value.

This comes from the value being bound like so:

<input data-role="combobox" data-text-field="text" data-value-field="value" id="cboSuffix" maxlength="20" data-bind="source: Suffixes, value: Contact.Suffix" style="width: 80px" />

It should have returned Suffix: "Sr."

Nothing else.

How do I get it to persist back just the actual value instead of both the value and the text from the combo item?

10 Answers, 1 is accepted

Sort by
0
Atanas Korchev
Telerik team
answered on 17 May 2012, 08:01 AM
Hello,

 I tried to reproduce the issue to no avail. Here is a jsFiddle demo which shows what I get: http://jsfiddle.net/korchev/ECG4L/1/ 

 What is different in your scenario?

Regards,
Atanas Korchev
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
James
Top achievements
Rank 1
answered on 18 May 2012, 01:18 PM
Here's the entire sample:

<fieldset id="contact-info" class="vertical-entry">
                    <legend>Contact Information</legend>
                    <table>
                        <tr>
                            <td><label for="cboSalutation">Salutation</label><select id="cboSalutation" data-role="dropdownlist" data-value-field="text" data-text-field="text" data-bind="source: Salutations, value: Contact.Salutation" style="width: 100px;" /></td>
                            <td><label for="txtFirstName">First Name</label><input type="text" maxlength="50" class="k-textbox" id="txtFirstName" data-bind="value: Contact.FirstName"  /></td>
                            <td><label for="txtLastName">Last Name</label><input type="text" maxlength="50" class="k-textbox" id="txtLastName" data-bind="value: Contact.LastOrCompanyName" /></td>
                        </tr>
                        <tr>
                            <td><label for="txtMiddleName">Middle Name</label><input type="text" maxlength="50" id="txtMiddleName" class="k-textbox" data-bind="value: Contact.MiddleName" style="width:  100px;" /></td>
                            <td><label for="cboSuffix">Suffix</label><input data-role="combobox" data-text-field="text" data-value-field="value" id="cboSuffix" maxlength="20" data-bind="source: Suffixes, value: Contact.Suffix" style="width: 80px" /></td>
                        </tr>
                    </table>
                    <input type="button" id="btnSubmitContactInfo" value="Save Contact Info" class="k-button" />
                </fieldset>


Here's the js:

var vmContact = new kendo.observable({
    Suffixes: [
        { value: null, text: ''},
        { value: 'Sr.', text: 'Sr.' },
        { value: 'Jr.', text: 'Jr.' },
        { value: 'III', text: 'III' },
        { value: 'IV', text: 'IV' },
        { value: 'V', text: 'V' }
    ],
    Salutations: [
        { text: "Mr." },
        { text: "Master" },
        { text: "Ms." },
        { text: "Mrs." },
        { text: "Miss." },
        { text: "Dr." }
    ],
    Contact: null
});
  
var dsContact = new kendo.data.DataSource({
    type: 'json',
    transport: {
        read: {
            url: "/api/v1/contacts/GetByID?id=" + ContactID,
            dataType: "json"              
        },
        update: {
            url: "/api/v1/contacts/Update",
            type: "PUT",
            contentType: "application/json; charset=utf-8",
            dataType: "json"
        },
        parameterMap: function (data, operation) {
            if (operation != "read") {
                return kendo.stringify([data]);
            }
        }
    },
    schema: {
        parse: function (data) {
            return [data];
        },
        model: {
            id: "ID"
        }
    },
    error: function (e) {
        debugger;
    }
});
  
  
dsContact.fetch(function (e) {
    vmContact.Contact = dsContact.data()[0];
  
    kendo.bind($("#contact-info"), vmContact);
});
 
 
    $("#btnSubmitContactInfo").click(function (e) {
        dsContact.sync();
    });


It sends the below json with both the value and the text instead of just the value as it should. (it's an input control because I cannot make it limit to max 20 characters in the combo box with MVVM when the user enters something other than a selection from the drop down list)

If you put a break on the kendo.stringify line and paste out what it's writes after you choose a combo box value for the suffix you'll see what I mean.
0
Atanas Korchev
Telerik team
answered on 18 May 2012, 01:35 PM
Hi James,

 What is the default value of Contact.Suffix? The combobox behaves differently depending on that.

If the initial value is null, undefined or object the combobox will set the selected data item.

Contact.Suffix = Suffixes[combobox.selectedIndex];

 If that value is of primitive type (number or string) the data-value-field would be used:

Contact.Suffix = Suffixes[combobox.selectedIndex].value;

I have demonstrated this behavior in the following jsFiddle: http://jsfiddle.net/korchev/Kut2g/1/ 

I guess Contact.Suffix is undefined or null in your case hence the combobox updates it with the selected suffix object. If you set Contact.Suffix to be empty string by default the combobox will update it with the "value" field of the selected suffix object.


Regards,
Atanas Korchev
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
James
Top achievements
Rank 1
answered on 18 May 2012, 01:50 PM
The value is null and SHOULD be null.

Which is an entirely valid value (no entry). It is even one of the possible values for the drop down as you'll note because your controls do not properly support null, so I had to hack it to put it in the list.

If the user specifies the DataFieldValue, then the correct and only value that should ever be returned is that value, not the entire object of the value and the text etc. If the end user doesn't specify the dataFieldValue then and only then should the entire object be the value. Thus this is clearly a bug. (and no I'm not going to work around it by putting an empty string into my database when the correct thing to store is no entry.)

Hopefully this can be fixed for next week's interim build.

Thanks.
0
Atanas Korchev
Telerik team
answered on 18 May 2012, 02:37 PM
Hello James,

 We do not consider this a bug. This is how the combobox MVVM support is implemented. It always needs data text field and data value field to be specified when binding to array of complex objects. We can't rely solely on the data value field being set when updating the view model.

 If you wan't only the data value field to be serialized you could set the default suffix value to empty string. Here is a simple implementation:

 

vmContact.Contact = dsContact.data()[0];
 
if (vmContact.Contact == null)
{
  vmContact.Contact = "";
}

Regards,
Atanas Korchev
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
James
Top achievements
Rank 1
answered on 18 May 2012, 03:04 PM
Sorry, but that's just a silly answer.

There should be no difference in behavior between null and empty string.

In fact the control should be nullable and have a property as such that allows "no entry" and literally sets the value to null instead of one of the items in the list.

There is never a case where it would be desirable to get back a value of an entire js object from the value when you've specified the dataValueField. It will ALWAYS be the value Field's value, nothing else other than null if no entry.

This is how your mvc controls work, this is how your asp.net controls work, this is how your win forms controls work, this is how your silverlight and wpf controls work, and finally, this is how every one of your competitors' jquery and other controls work.

Thus your implementation is at best highly non-standard, but I'd strongly suggest that it's clearly a bug.

If the user does not specify the dataValueField then it should return the entire object otherwise it should return the value. It should have this behavior 100% of the time without exception. Anything else causes random bugs because of different behavior in different settings.

(And your work around doesn't work for round tripping null to the server without a massive amount of code every single time this occurs. Given that essentially every time you use a drop down or a combo control, null is an entirely valid value, this means that you have to put hack code in to fix this garbage result you're returning every single time.)

This is exactly what I"m talking about about broken controls that are poorly thought out. You aren't thinking about actual usage scenarios carefully.

I strongly encourage you to get with whomever makes these decisions ASAP and get this fixed. If anyone looks at this remotely logically you'll agree with me. This is head slappingly obvious and I shouldn't be having to waste my time dealing with these inconsistencies in your controls.

 (and while you're at it, fix it so that it handles null properly like every other combo control you guys create and every other combo control everyone else has ever created by giving it a nullable property, set the default to true. And while you're at it, add limittoList and autoComplete as well so that it auto completes, and incrementally selects and fills in the text in the box as you type but allows over-typing and requires that the user either select null (if nullable) or a valid value. so that your combo control follows standard and expected behavior instead of the inconsistent, non-standard implementation that it is now.)

And sorry to make this public, but you respond about 5x faster to your public forums than your paid support. I'm averaging 48-72 hours for support to get back to me, and a few hours for a forum response, so I've taken to using the forums. I'd say these things privately (and have) if I got a response in a reasonable time frame.
0
Atanas Korchev
Telerik team
answered on 21 May 2012, 03:06 PM
Hello James,

Up to your comments:

"Sorry, but that's just a silly answer."
I am sorry to hear this. I thought that I clearly explained the intentions of this behavior and demonstrated a workaround for your particular scenario. It seems that you just don't want to accept the fact that Kendo UI does not work the way you expect it to. 

"There should be no difference in behavior between null and empty string."
Well there is a difference and I explained that difference two times already. I don't think I should explain it for the third time.

"In fact the control should be nullable and have a property as such that allows "no entry" and literally sets the value to null instead of one of the items in the list."
The placeholder setting can be used to achieve a similar thing: http://jsfiddle.net/korchev/Kut2g/2/ 

"There is never a case where it would be desirable to get back a value of an entire js object from the value when you've specified the dataValueField.  "
You always need to specify data value field when binding to an array of JavaScript objects. I also said that there are quite a lot of customers who depend exactly on that behavior. What should we tell those customers if we decide to no longer support that? On a side note having the entire JS object to be the value of the combobox is a well known behavior and this is how other popular MVVM JS libraries such as KnockoutJS work. Check the first look example of KnockoutJS: http://knockoutjs.com/ - it shows exactly the same thing. I guess there are quite a lot of cases when this behavior is desirable. 

"This is how your mvc controls work, this is how your asp.net controls work, this is how your win forms controls work, this is how your silverlight and wpf controls work, and finally, this is how every one of your competitors' jquery and other controls work."
This statement is ambiguous at best. Telerik Extensions for ASP.NET MVC and RadControls for ASP.NET Ajax do not support any MVVM style binding. Thus they cannot be compared with Kendo UI regarding this exact behavior. Just to make things clearer - the data value field of the Kendo combobox will be posted if you are submitting a regular form. RadComboBox for Silverlight has a SelectedItem property which returns the currently selected object from the data source: http://www.telerik.com/help/silverlight/radcombobox-features-selection.html#Using_the_SelectedItem - a behavior quite similar to the way Kendo MVVM works.


"Thus your implementation is at best highly non-standard, but I'd strongly suggest that it's clearly a bug."
The first look KnockoutJS example and the way mvvm binding works in XAML tell the opposite. 
 
"I strongly encourage you to get with whomever makes these decisions ASAP and get this fixed."
Actually I am the product lead of Kendo UI and I am making these decisions. As I have said many times before we are not going to change this behavior.

"and while you're at it, fix it so that it handles null properly like every other combo control you guys create"
I can't recall a single Telerik control having such a property. I have taken part in the development of RadComboBox for ASP.NET Ajax, Combobox for ASP.NET MVC and ComboBox for Kendo UI - none of them support such a setting. The default <select> element doesn't support null values either.

"I'm averaging 48-72 hours for support to get back to me"
Telerik guarantees 48 hours response time in business days (Mo-Fri) as noted in our support options page: http://www.kendoui.com/support-options.aspx 
I've checked your support ticket history and all tickets seem to have been answered within the 48 hour limit.

Regards,
Atanas Korchev
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
James
Top achievements
Rank 1
answered on 21 May 2012, 04:53 PM
1. Your "solution" is to eliminate all null values enitrely or get a bogus value from the control. Since null is an entirely valid value, and required for key (i.e. CategoryID = null means no entry and thus no actual value, nor "" is valid and cannot be persisted) entry when the user does not make a selection does not work.

It may work in the simple case I gave you were the value is  a string. It doesn't work if the value is an int that will be persisted to the database and 0 is entirely valid key and the column is nullable. 

Thus your solution is broken and does not address the actual issue: You must support NULL. You currently do not thus your controls in MVVM mode (and from other posts in non-mvvm mode) are useless for any database persistance because null is both a common entry and required. 

However you dance around all of the rest of Telerik's controls having a consistent value that is either null, or a valid value in the drop down as specified by the Value Field property, they ALL DO. It doesn't matter if they're using MVVM (like Silverlight and WPF controls that I just tested and your versions of these controls handle null by returning null and do not ever return anything other than null or the valid selected Value Field value specified.) or anything else. The only correct value null or a valid value field value. Anything else is an inconsistent value that cannot be round tripped from and to a database which is the entire point of MVVM and all other data binding.

But then this is nothing new. Your data source control doesn't work with any framework out there when doing a DELETE request. Yes jquery is broken and you're copying their functionality, but guess what? There are several bug reports in the jquery bug tracker about this very issue. You should be working around their bug until it is fixed. But no, you find it acceptable that .NET web services cannot get the values passed in a DELETE request, google web hosting returns BADREQUEST, as does amazon hosting, and the java server side equivalent. (And I've provided you with links proving all of these.) Thus you've been provided with ample evidence that your default configuration is broken and can't work with any of the major hosting companies, and yet you refuse to fix it. It's not like it's going to harm anyone's current implementation, because it simply won't work anyhow. Heck the RFC itself clearly states that your implementation is wrong (which I've already sent to you as well)

Think logically about both of these issues. Ask yourself if your "solution" works for the most basic of cases. (they don't). MVVM's purpose is for fast data binding and persistence to a data store while detaching the binding from the view. That's what it's for. But your solution prevents it from doing it's job. It just won't work. You justify otherwise but it won't.

Your data source will not work against ANY REST STANDARDS COMPLIANT SERVER. But you think that's OK because you are just passing it to jquery to handle and you think because they have a bug that its OK for you to have the same.

2. Your 24 hour guarantee is bunk. Look again. I have several that took 5 days to respond according to the date and time stamps on your own ticketing system. Even taking off two over a weekend, that's still 3 days to respond. Either your ticketing system is presenting bogus dates and times (possible given the number of other bugs in it that I've sent you about your ticketing system) or you're not responding in your own stated time guarantee.

And even if it was in 48 hours (they're not) that's unacceptable for massively broken implementations, poor documentation (which you've already admitted) and an immature product. You cannot expect people to develop with your product professionally when the simplest things that are not documented or poorly documented require 48 hours to be able to do any further coding. 
0
Atanas Korchev
Telerik team
answered on 21 May 2012, 05:20 PM
Hi,

 We don't seem to make any progress here. You keep insisting that we should implement Kendo features the way you want them to work. 

Up to your comments:

"null is both a common entry and required."

How do you handle this case if Kendo UI is not involved? How would you implement this using the regular <select> HTML element which does not support null values? How exactly do you expect this feature to work? How should  "null" be posted in a regular HTTP POST request (in a form for example)?

"However you dance around all of the rest of Telerik's controls having a consistent value that is either null, or a valid value in the drop down as specified by the Value Field property"
This is not entirely true. Check the link to the documentation of the SelectedItem property which I included in my previous reply. I agree that when posting the value specified by data value field should be posted. But this is exactly how the Kendo combobox behaves if MVVM were not involved. Using the selected object in MVVM binding scenarios is a common practice (check KnockoutJS which is one of the most commonly used MVVM JavaScript binding libraries).

"Your data source control doesn't work with any framework out there when doing a DELETE request."
This is not true. Currently we have a Ruby on Rails example which performs DELETEs: https://github.com/telerik/kendo-examples-rails/blob/master/app/views/expenses/index.html.erb#L26 I believe that my colleagues have already shown you how to do the same in ASP.NET MVC.

"Your 24 hour guarantee is bunk"
We don't guarantee 24 hour response times. Our guaranteed response time is 48 hours.

"I have several that took 5 days to respond according to the date and time stamps on your own ticketing system".
Could you please give me the IDs of those late support tickets? I would like to check what caused the delayed response.

All in all it seems that neither Kendo UI nor Telerik meet your expectations. Perhaps it would be best if you find a product which better suits your needs and works the way you expect it to.

All the best,

Atanas Korchev
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
James
Top achievements
Rank 1
answered on 21 May 2012, 05:56 PM
How do you handle this case if Kendo UI is not involved? How would you implement this using the regular <select> HTML element which does not support null values? How exactly do you expect this feature to work? How should  "null" be posted in a regular HTTP POST request (in a form for example)? 

It's irrelevant if the <select> does not support null (it actually does, you just have to set the first item to have a value of Null and then some text as the text param, thus manually giving null as a valid entry and providing it in the drop down). The reason to purchase your controls and NOT use the standard controls is because your controls are supposedly better than those. That's why you wrap them with other special elements and don't require that a <select> element be the basis for the combo or drop down controls, in fact they're all <input> controls where null is entirely valid.

Here's json:

[
{
"Name": "Some Product",
"CategoryID": 1
},
{
"Name": "Some Product 2",
"CategoryID": null
}

Given that there would be absolutely no reason to use MVVM with a form post because by definition a form post has the controls already bound to the data I fail to see why that would matter.

However if you wanted to post with standard MVClike form fields you would simply pass null in the kvp which .net and every other environment that I've tested (RoR, java and a few others on top of MVC.NET) all accept this and deserialize it just fine.

All other values would return the actual value specified from the property specified in the Value Field setup option. (and in the case of a combo control with LimitToList = false the user's typed text is also a valid value)

This is not entirely true. Check the link to the documentation of the SelectedItem property which I included in my previous reply. I agree that when posting the value specified by data value field should be posted. But this is exactly how the Kendo combobox behaves if MVVM were not involved. Using the selected object in MVVM binding scenarios is a common practice (check KnockoutJS which is one of the most commonly used MVVM JavaScript binding libraries). 

The VALUE property is always the data value field specified value. The SelectedItem property is NOT WHAT YOU BIND TO OF COURSE and are two entirely different things. Hence why I ignored what you wrote because it was an evasion.

As for knockout, when used against a select that doesn't have a null value explicitly in the list of options, it throws an error if bound to null. It doesn't create weird and wild results where if you then select a value it comes back with the entire element instead of just the value but only if null was passed to it in the first place, and in every other case it works just fine.

If bound to an input which you then javascript your way around a drop down on, it will correctly clearly the entry of the input. (which is what you guys are doing thus it would work fine)

DELETEs: https://github.com/telerik/kendo-examples-rails/blob/master/app/views/expenses/index.html.erb#L26 I believe that my colleagues have already shown you how to do the same in ASP.NET MVC. 

Host the RoR example on Amazon or Google. FAIL.

The solution for ASP.NET MVC is to implement on every data source custom code that properly parameterizes the IDs and passes them as part of the URL and then override the parametermap function and make sure that any delete requests return null. Otherwise MVC.NET and more importantly going forward WEB API get NO DATA. It doesn't error, but it fails because it's not valid and the deserializer will not deserialize the body of a DELETE.

Further as I've already posted to support (Right from the RFC that defines how DELETE SHOULD WORK):

9.7 DELETE

The DELETE method requests that the origin server delete the resource identified by the Request-URI. This method MAY be overridden by human intervention (or other means) on the origin server. The client cannot be guaranteed that the operation has been carried out, even if the status code returned from the origin server indicates that the action has been completed successfully. However, the server SHOULD NOT indicate success unless, at the time the response is given, it intends to delete the resource or move it to an inaccessible location.

I defy anyone with any programming experience to be confused as to what that means.Request-URI means one thing and one thing only: The full URL with parameters. Content is NOT SUPPORTED and thus any DELETE request with content is NOT VALID.

So again it's a bug. You're sending bogus data over the wire as per the RFC documentation. That a few web servers will allow this is irrelivent. The majority do not and the RFC clearly states that your method is WRONG

(I've also provided you with examples and proof of how to handle this correctly in batch mode as well but been ignored.)

I've also provided you with code that I wrote hacking your odata source in an attempt to automate all of the things that are inconsistent out of the box with the data source. I asked 3 simple questions that I needed work arounds. I got "it doesn't work that way" instead of an actual work around. All were related to this issue. If you're unwilling to fix your bugs, then at least work with the person to hack it to work the right and expected way.


We don't guarantee 24 hour response times. Our guaranteed response time is 48 hours. 

Sorry for the typo: See the Delete Batch support issue under my file. I have the post dates and times for my issues and your response dates and times in addition to the now removed Time portion that used to be in the support section. (directly from my mail server's SMTP receive log to ensure that it wasn't an issue with the mail client)

There are several cases where issues were posted Friday morning < 10 am eastern and responses were not given until Tuesday after 6 pm eastern. If you mean ~2 days then say ~2 days. If you mean 48 hours, then be clear.

But again with such an immature product (you've admitted as much in support tickets) with such bad documentation I'd suggest that 48 hours is completely unacceptable as I've previously outlined.
Tags
MVVM
Asked by
James
Top achievements
Rank 1
Answers by
Atanas Korchev
Telerik team
James
Top achievements
Rank 1
Share this question
or