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

Knockout Tutorial #2

13 Answers 454 Views
MVVM
This is a migrated thread and some comments may be shown as answers.
Phil
Top achievements
Rank 2
Phil asked on 28 Oct 2012, 04:36 PM
Hi:

I am trying to convert the Knockout tutorial #2 to Kendo MVVM.  Learn knockout Tutorial Collections
Not doing well.
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Tutorial2_4.aspx.cs" Inherits="KnockoutApp.Tutorials.Tutorial2_3" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
<style type="text/css">
    .deleteLink
    {
        color: red;
        font-weight: bold;
    }
</style>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <!-- -->
    <div id="mvvmRegion">
        <h2>Your seat reservations (<span data-bind="text: seats.length" ></span>)</h2>
        <button id="addSeatButton" data-bind="click: addSeat">Reserve another seat</button>
        <div style="width: 600px;">
        <table id="reservationTable">
            <thead><tr>
                <th data-field="name" style="width: 160px;">Passenger name</th>
                <th data-field="meal.mealName" style="width: 160px;">Meal</th>
                <th data-field="meal.price" style="width: 100px;">Surcharge</th>
                <th> </th>
            </tr></thead>
            <tbody>
            </tbody>
        </table>
        </div>
        <h3 data-bind="visible: surcharge">
            Total surcharge: $<span data-bind="text: totalSurcharge00"></span>
        </h3>
    </div>
<script id="reservationTemplate" type="text/x-kendo-template">
<tr>
    <td style="width: 160px;"><input id="nameTextBox" value="#= name #" data-bind="value: seats.name" /></td>
    <td style="width: 160px;"><input id="mealDropDown" class="mealDropDownClass" value="#= meal.mealName #" data-bind="value: seats.meal.mealName" /></td>
    <td style="width: 100px;">#= meal.price #</td>
    <td><a href="" class="deleteLink">Remove</a></td>
</tr>
</script>
    <script type="text/javascript">
        // Class to represent a row in the seat reservations grid
        function SeatReservation(fname, initialMeal) {
            var self = this;
            self.name = fname;
            self.meal = initialMeal;
        }
        //
        var availableMeals = [
            { mealName: "Standard (sandwich)", price: 0.0 },
            { mealName: "Premium (lobster)", price: 34.95 },
            { mealName: "Ultimate (whole zebra)", price: 290.0 }
        ];
        //
        var viewModel = kendo.observable({
            // type array populates the drop down
            meals: availableMeals,
            // array will hold the grid values
            seats: [
            new SeatReservation("Steve", availableMeals[1]),
            new SeatReservation("Bert", availableMeals[0])
            ],
            // Computed data
            totalSurcharge: function () {
                var total = 0;
                for (var i = 0; i < this.get("seats").length; i++)
                    total += this.get("seats")[i].meal.price;
                return total + 0.00;
            },
            totalSurcharge00: function () {
                var total = this.totalSurcharge() + 0.00;
                return total.toFixed(2);
            },
            surcharge: function () {
                var total = this.totalSurcharge() + 0.00;
                if (total > 0) return true;
                return false;
            },
            //
            maxSeating: function () {
                if (this.seats.length < 5) return true;
                return false;
            },
            // seats.length < 5
            // event execute on click of add button
            addSeat: function (e) {
                // add the items to the array of expenses
                this.get("seats").push(new SeatReservation("", self.availableMeals[1]));
                return false;
            },
            removeSeat: function (seat) {
                var seats = this.get("seats");
                seats.splice(seats.indexOf(seat), 1);
            }
        });
        // apply the bindings
        kendo.bind($("#mvvmRegion"), viewModel);
        //
        var reservationDataSource = new kendo.data.DataSource({
            data: viewModel.get("seats"),
            schema: {
                model: {
                    id: "name",
                    fields: {
                        // data type of the field {Number|String|Boolean|Date} default is String
                        name: { type: "String" },
                        meal: {
                            mealName: { type: "String" },
                            price: { type: "Numeric" }
                        }
                    }
                }
            }
        });
        //
        $("#reservationTable").kendoGrid({
            dataSource: reservationDataSource,
            rowTemplate: kendo.template($("#reservationTemplate").html()),
            dataBound: function (e) {
                $(".deleteLink").click(function (e) {
                    e.preventDefault();
                    if (confirm("Do you what to delete this?")) {
                        var grid = $("#reservationTable").data("kendoGrid");
                        var dataItem = grid.dataItem($(this).closest("tr"));
                        viewModel.removeSeat(dataItem);
                    }
                    return false;
                });
            }
        });
        $(".mealDropDownClass").kendoDropDownList({
            dataTextField: "mealName",
            dataValueField: "mealName",
            dataSource: availableMeals
        });
        //
    </script>
</asp:Content>

Problem is the binding is not happening and the dropdown loses it's dropdownlist on add or remove. 

Note: Kendo does not seem to have the calculated (logical) binding like Knockout does for visible and enabled.

Phil

13 Answers, 1 is accepted

Sort by
0
Phil
Top achievements
Rank 2
answered on 28 Oct 2012, 10:37 PM
Hi:

I have gotten the following logical to work:
<h3 data-bind="visible: totalSurcharge() > 0">
    Total surcharge: $<span data-bind="text: totalSurcharge00()"></span>
</h3>

Phil
0
Phil
Top achievements
Rank 2
answered on 31 Oct 2012, 11:37 PM
Hi:
I have come to the conclusion that MVVM does not support data-bind (update) of arrays such as in Knockout tutorial #2.
Phil
0
Alexander Valchev
Telerik team
answered on 05 Nov 2012, 01:13 PM
Hi Phillip,

Actually KendoUI supports binding to arrays. A similar to your scenario can be accomplished through the source and template binding. Here is an example:
Please note that Kendo MVVM bindings are not JavaScript. This means that in order to display the meal's name and price you have to use functions in the View-Model.

For more information please check the MVVM help topics which could be found in the documentation.

Kind regards,
Alexander Valchev
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Phil
Top achievements
Rank 2
answered on 06 Nov 2012, 12:23 AM
Hi:

I am very familiar with the Source and Template Binding.  The data binding in Kockout supports binding to an array of classes.  Changes to an element in a class is handled by the Knockout model.  The Knockout model knows that elements in the in the array of structures has changed and is updated.  In all of the api for observablearray, the arrays are of simple types.  No demo that I have found seem to support an array of classes/structure.  I think that is because MVVM does not currently support it.  MVVM binds the adding and removing of elements of the array.
This is the tutorial #2:
<!DOCTYPE html>
<html>
<head>
    <title>Knockout Tutorial 2</title>
    <script type="text/javascript" src="../Scripts/knockout-2.1.0.js"></script>
</head>
<body>
    <!-- learn.knockoutjs.com -->
    <h2>Your seat reservations (<span data-bind="text: seats().length" ></span>)</h2>
    <button data-bind="click: addSeat, enable: seats().length < 5">Reserve another seat</button>
    <table>
        <thead><tr>
            <th>Passenger name</th><th>Meal</th><th>Surcharge</th><th></th>
        </tr></thead>
        <tbody data-bind="foreach: seats">
            <tr>
                <td><input data-bind="value: name" /></td>
                <td><select data-bind="options: $root.availableMeals, value: meal, optionsText: 'mealName'"></select></td>
                <td data-bind="text: formattedPrice"></td>
                <td><a href="#" data-bind="click: $root.removeSeat">Remove</a></td>
            </tr>  
        </tbody>
    </table>
    <h3 data-bind="visible: totalSurcharge() > 0">
        Total surcharge: $<span data-bind="text: totalSurcharge().toFixed(2)"></span>
    </h3>
    <script type="text/javascript">
        // Class to represent a row in the seat reservations grid
        function SeatReservation(name, initialMeal) {
            var self = this;
            self.name = name;
            self.meal = ko.observable(initialMeal);
            self.formattedPrice = ko.computed(function () {
                var price = self.meal().price;
                return price ? "$" + price.toFixed(2) : "None";
            });
        }
        // Overall viewmodel for this screen, along with initial state
        function ReservationsViewModel() {
            var self = this;
            // Non-editable catalog data - would come from the server
            self.availableMeals = [
                { mealName: "Standard (sandwich)", price: 0 },
                { mealName: "Premium (lobster)", price: 34.95 },
                { mealName: "Ultimate (whole zebra)", price: 290 }
            ];
            // Editable data
            self.seats = ko.observableArray([
                new SeatReservation("Steve", self.availableMeals[0]),
                new SeatReservation("Bert", self.availableMeals[0])
            ]);
            // Computed data
            self.totalSurcharge = ko.computed(function () {
                var total = 0;
                for (var i = 0; i < self.seats().length; i++)
                    total += self.seats()[i].meal().price;
                return total;
            });
            // Operations
            self.addSeat = function () {
                self.seats.push(new SeatReservation("", self.availableMeals[0]));
            }
            self.removeSeat = function (seat) { self.seats.remove(seat) }
        }
        ko.applyBindings(new ReservationsViewModel());
    </script>
</body>
</html>

Phil
0
Florian
Top achievements
Rank 1
answered on 06 Nov 2012, 11:50 AM
Phil,

what's your conclusion? Using MMVC from kendo or Knockout?
I am having problems with the kendo MMVC and have to make a decision...

Thanks
Florian
0
Phil
Top achievements
Rank 2
answered on 07 Nov 2012, 12:46 AM
Hi:

One of my funtions at the company that I work at is Lead Technologist.  I set directions.  Late in 2008, I got the company to buy Telerik Suite.  I am re-evaluating that at this time and Telerik has not sold me.  First the information on the produce is not rich. They do have the Dojo for learning, but that is very elementary.  The demos and examples have not for me given me a clear understanding of the entire Kendo UI product.  For example, this post.  Telerik seem to be in denial that it needs some improvement.

If you want free, go with Knockout, jQueryUI with extra styling with Twitter Bootstrap.  Kendo UI is not free, but it is integrated and some support.  I have not made up my mind yet.

Phil
0
Florian
Top achievements
Rank 1
answered on 07 Nov 2012, 06:29 AM
Hi Phil,

thanks for your reply! It's very valuable to me.

Your opinion supports my impression. There are improvements missing. And the documentation is extremly unstructured and makes finding information very time-consuming.

Greetings from Austria
Florian
0
Alexander Valchev
Telerik team
answered on 08 Nov 2012, 02:22 PM
Hi guys,

MVVM binding to nested arrays is supported. Here is a very basic example: http://jsbin.com/ezicuh/2/edit

I believe that the main confusion comes from the fact that Kendo MVVM bindings are not JavaScript. This pattern is documented and we do not have a plans to change it. If you insist to use Kendo with KnockoutJS you may take a look at this project. Please have in mind that this library is not our product and any questions related to it are not covered by the support service.

Regards,
Alexander Valchev
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Phil
Top achievements
Rank 2
answered on 09 Nov 2012, 03:05 AM
Hi:
Wow this mostly works!  When I tab off of the last field it does not update the span tag.
@{
    ViewBag.Title = "Array Binding with Template";
}
<h2>ArrayBinding</h2>
<div id="example" data-template="tmp" data-bind="source: mySource"></div>
<script id="tmp" type="text/x-kendo-template">
    <div class="item">
        <input data-bind="value: data.name" class="k-textbox k-input" /> <input type="numeric" data-bind="value: data.age" class="k-textbox k-input" />
        <span data-bind="text: item"></span> <span data-bind="text: data.name"></span>,  <span data-bind="text: data.age"></span>
    </div>
</script>
<script type="text/javascript">
    var viewModel = kendo.observable({
        mySource: [
            {   item: "Item1",
                data: { name: "Name1", age: "33" } },
            {   item: "Item2",
                data: { name: "Name2", age: "43" } }
        ]
    });
    kendo.bind($("#example"), viewModel);
</script>
Phil
0
Phil
Top achievements
Rank 2
answered on 10 Nov 2012, 01:25 AM
Hey Florian:

It just hit me.  The Kendo product is so big that Telerik has teams that handle a specific area.  So, you have a DataSource person that doesn't have grid experience, so they use div and span tags.  The same for MVVM specialist does the same.  So, the fragmentation of Telerik is confusing and not giving a clear view of the produce.

Hey, Telerik you need cross training in your own produce.

Phil
0
Phil
Top achievements
Rank 2
answered on 10 Nov 2012, 03:16 AM
Hi:

I have gotten a grid to work with http://jsbin.com/ezicuh/7/edit, which uses a not release version of 2012.3.1024.  I have the latest Kendo UI 2012.2.913 which does not seem to work.

Phil
0
Florian
Top achievements
Rank 1
answered on 10 Nov 2012, 07:32 AM
Hey Phil,

your are definitely right! My experience is that the quality of technical answers depends on the Telerik person responible.

You find a drastical sample here: http://www.kendoui.com/forums/ui/dropdownlist/accessing-check-box-template-from-inside-dropdownlist.aspx

A user asks if the Telerik library supports a specific use case. Telerik says no. And somebody from our community publishes sample code with the solution! That's really a shame...

Florian
0
Phil
Top achievements
Rank 2
answered on 10 Nov 2012, 06:59 PM
Hi:
I have some crow to eat, maybe ...
The problem is not versions.  I normally browse the internet with FF, but my default browser is IE 9.  So, when I click on an item on the web I am using FF.  When I run a web project IE is launched.  So the problem is browser (the most used browser in the States).
Phil
Tags
MVVM
Asked by
Phil
Top achievements
Rank 2
Answers by
Phil
Top achievements
Rank 2
Alexander Valchev
Telerik team
Florian
Top achievements
Rank 1
Share this question
or