【ASP.NET MVC】【VB】ASP.NET MVC で変更検知を考える ~hiddenを使った版~


サンプル

前回までの実装
http://blogs.yahoo.co.jp/dk521123/35964974.html
http://blogs.yahoo.co.jp/dk521123/35963034.html
と比べると、比較対象の値を保持する必要があるので、モデルを変更している
それをhiddenに保持しておいて、JavaScriptで比較しているだけ。

■モデル

MainListModel.vb
Imports System.Collections.Generic

Namespace Models
    Public Class MainListModel
        Public Property Employees As List(Of MainModel)
        Public Sub New()
            Me.Employees = New List(Of MainModel)
        End Sub
    End Class

    Public Class MainModel
        Public Property model As EmployeeModel
        Public Property originalValueModel As EmployeeModel
    End Class

    Public Class EmployeeModel
        Implements ICloneable
        Public Property IsChecked As Boolean
        Public Property EmployeeId As String
        Public Property EmployeeName As String

        Public Function Clone() As Object Implements ICloneable.Clone
            Return EmployeeId.Clone()
        End Function
    End Class

End Namespace

■コントローラ

SampleMvcController.vb
Imports System.Web.Mvc
Imports WebAppli.Models

Namespace Controllers
    Public Class SampleMvcController
        Inherits Controller

        Function Index() As ActionResult
            Dim model = New MainListModel()
            model.Employees = New List(Of MainModel) From
            {
                New MainModel() With
                {
                    .model = New EmployeeModel() With {.IsChecked = False, .EmployeeId = "X001", .EmployeeName = "Mike"},
                    .originalValueModel = New EmployeeModel() With {.IsChecked = False, .EmployeeId = "X001", .EmployeeName = "Mike"}
                },
                New MainModel() With
                {
                    .model = New EmployeeModel() With {.IsChecked = True, .EmployeeId = "X002", .EmployeeName = "Tom"},
                    .originalValueModel = New EmployeeModel() With {.IsChecked = True, .EmployeeId = "X002", .EmployeeName = "Tom"}
                },
                New MainModel() With
                {
                    .model = New EmployeeModel() With {.IsChecked = True, .EmployeeId = "Y001", .EmployeeName = "Smith"},
                    .originalValueModel = New EmployeeModel() With {.IsChecked = True, .EmployeeId = "Y001", .EmployeeName = "Smith"}
                },
                New MainModel() With
                {
                    .model = New EmployeeModel() With {.IsChecked = False, .EmployeeId = "Z001", .EmployeeName = "Kevin"},
                    .originalValueModel = New EmployeeModel() With {.IsChecked = False, .EmployeeId = "Z001", .EmployeeName = "Kevin"}
                }
         }

            Return View(model)
        End Function

        Function SendResult(ByVal model As MainListModel) As ActionResult
            Return View(model)
        End Function

    End Class
End Namespace

■ビュー

Index.vbhtml
@ModelType WebAppli.Models.MainListModel

@Code
    ViewData("Title") = "Index"
    Dim index As Integer = 0
End Code

@Using (Html.BeginForm("SendResult", "SampleMvc", FormMethod.Post, New With {.Id = "formID"}))
    @<table>
        <thead>
            <tr>
                <th>Checked?</th>
                <th>ID</th>
                <th>Name</th>
            </tr>
        </thead>
        <tbody>
            @For index = 0 To Model.Employees.Count - 1 Step 1
                @<tr>
                    <td>@Html.CheckBoxFor(Function(model) model.Employees(index).model.IsChecked)</td>
                    <td>@Html.TextBoxFor(Function(model) model.Employees(index).model.EmployeeId)</td>
                    <td>@Html.TextBoxFor(Function(model) model.Employees(index).model.EmployeeName)</td>
                </tr>
                @Html.HiddenFor(Function(model) model.Employees(index).originalValueModel.IsChecked, Nothing)
                @Html.HiddenFor(Function(model) model.Employees(index).originalValueModel.EmployeeId, Nothing)
                @Html.HiddenFor(Function(model) model.Employees(index).originalValueModel.EmployeeName, Nothing)
            Next
        </tbody>
    </table>
    @<input type="submit" value="Send" />
    @<a href="http://www.yahoo.co.jp/" onclick="return checkToChangeValues()">Go yahoo!</a>
End Using

<script type="text/javascript">
    function checkToChangeValues() {
        if (areCheckeValues()) {
            return confirm(
                'You have some changes.\nAre you sure you want to go to the other pages?');
        }
        return true;
    }

    function areCheckeValues() {
        @For index = 0 To Model.Employees.Count - 1 Step 1
        @<text>
        if (isCheckedValue(
            "@Html.IdFor(Function(model) model.Employees(index).model.IsChecked)",
            "@Html.IdFor(Function(model) model.Employees(index).originalValueModel.IsChecked)",
            true) ||
            isCheckedValue(
            "@Html.IdFor(Function(model) model.Employees(index).model.EmployeeId)",
            "@Html.IdFor(Function(model) model.Employees(index).originalValueModel.EmployeeId)",
            false) ||
            isCheckedValue(
            "@Html.IdFor(Function(model) model.Employees(index).model.EmployeeName)",
            "@Html.IdFor(Function(model) model.Employees(index).originalValueModel.EmployeeName)",
            false)) {
            return true;
        }
        </text>
        Next

        return false;
    }

    function isCheckedValue(targetId, originalValueId, isCheckedControl) {
        var targetObject = document.getElementById(targetId);
        var originalValueObject = document.getElementById(originalValueId);

        var targetValue;
        var originalValue;
        if (isCheckedControl) {
            targetValue = targetObject.checked;
            originalValue = parseBoolean(originalValueObject.value);
        } else {
            targetValue = targetObject.value;
            originalValue = originalValueObject.value;
        }

        if (targetValue != originalValue) {
            return true;
        }
        return false;
    }
    
    function parseBoolean(targetValue) {
        if (!targetValue) {
            return false;
        }
   
        return (targetValue.toLowerCase()) == "true";
    }
</script>
SendResult.vbhtml
@ModelType WebAppli.Models.MainListModel

@Code
    ViewData("Title") = "SendResult"
End Code

<h2>SendResult</h2>

<table>
    <thead>
        <tr>
            <th>Check?</th>
            <th>ID</th>
            <th>Name</th>
        </tr>
    </thead>
    <tbody>
        @For Each employee In Model.Employees
            @<tr>
                <td>@employee.model.IsChecked</td>
                <td>@employee.model.EmployeeId</td>
                <td>@employee.model.EmployeeName</td>
            </tr>
        Next
    </tbody>
</table>

関連記事

ASP.NET MVC で変更検知を考える ~簡易版~

http://blogs.yahoo.co.jp/dk521123/35963034.html

ASP.NET MVC で変更検知を考える ~knockout.js利用版~

http://blogs.yahoo.co.jp/dk521123/35964974.html