首页 > 解决方案 > Knockout 和 ASP.NET MVC 编辑表单在映射后显示重复行

问题描述

大家早上好,我搜索了这个问题,但我找不到它。我正在尝试在带有淘汰赛的 asp.net mvc 应用程序中编辑报价,其中包含嵌套集合和计算变量

创作进展顺利。但是编辑表单显示重复的行。就好像服务器显示它的数据,而 KNOCKOUT 也显示它自己的一样。

当我在控制台中查看时,我的淘汰模式被正确地调用了我正在使用编辑器模板的次数。

我的淘汰赛:

var QuotationDetail = function (data) {

        var self = this;

                var productsData = @Html.Raw(Json.Encode(ViewBag.Products));
        self.productCategories = ko.observableArray(productsData);


        if (data != null) {
            self.QuotationId = ko.observable();
            self.Id = ko.observable();


            self.Quantity = ko.observable(data.Quantity);
            self.Discount = ko.observable(data.Discount);
            self.UniteQuotation = ko.observable(data.UniteQuotation);
            self.Description = ko.observable(data.Description);
            self.ProductCategory = ko.observable();
            self.Product = ko.observable();
            self.PriceUnit = ko.observable(data.PriceUnit);

            self.ProductName = ko.observable(data.ProductName);
            self.PriceHT = ko.pureComputed(function () {
                return self.PriceUnit() ? self.PriceUnit() * parseInt("0" + self.Quantity(), 10) - ((self.PriceUnit() * parseInt("0" + self.Quantity(), 10) * parseFloat("0" + self.Discount()) / 100)) : 0;
            });
     

        } else {
            self.QuotationId = ko.observable();
            self.Id = ko.observable();

            console.log('pas de données');
            self.Quantity = ko.observable(1);
            self.Discount = ko.observable(0);
            self.UniteQuotation = ko.observable();
            self.Description = ko.observable();
            self.ProductCategory = ko.observable();
            self.Product = ko.observable();
            self.PriceUnit = ko.observable();

            self.ProductName = ko.observable();
            self.PriceHT = ko.pureComputed(function () {
                return self.PriceUnit() ? self.PriceUnit() * parseInt("0" + self.Quantity(), 10) - ((self.PriceUnit() * parseInt("0" + self.Quantity(), 10) * parseFloat("0" + self.discount()) / 100)) : 0;
            });
            self.Product.subscribe(function () {
                if (self.Product()) {
                    self.PriceUnit(self.Product().ProductPrice);
                    self.ProductName(self.Product().Title);
                    self.Description(self.Product().Description);
                }
                else {
                    self.priceunit(0);
                }

            });
        }
       
            // fin

    };

    var mapping = {

        create: function (options) {
            return new QuotationDetail(options.data);
        }
    }
    var Quotation = function () {

        var self = this;
      
         var data = @Html.Raw(Json.Encode(Model.QuotationDetails));
        console.log('Lancement du mapping des détails : ' + JSON.stringify(data));

        self.lines = ko.mapping.fromJS(data, mapping);

        //self.lines = ko.observableArray(ko.utils.arrayMap(appdatas, function (line) {
        //    return new QuotationDetail(line);
        //}));
           //self.lines = ko.utils.arrayMap(appdatas, function (data) { return new QuotationDetail(data); });
      


        self.discountgeneral = ko.observable(0);

        var dataTvas = @Html.Raw(Json.Encode(ViewBag.TVAs));
        console.log(JSON.stringify(dataTvas));
        self.tvas = ko.observableArray(dataTvas);

        self.tva = ko.observable();
        self.grandTotalService = ko.pureComputed(function () {
            var totalService = 0;
            $.each(self.lines(), function () { totalService += this.PriceHT() })
            return totalService;
        });
        // Put one line in by default
        self.grandTotalHT = ko.pureComputed(function () {
            var totalHT = 0;
            $.each(self.lines(), function () { totalHT += this.PriceHT() - (this.PriceHT() * parseFloat("0" + self.discountgeneral()) / 100) })
            return totalHT;
        });

        self.grandTotalDisc = ko.pureComputed(function () {
            var totalDisc = 0;
            $.each(self.lines(), function () { totalDisc += (this.PriceHT() * parseFloat("0" + self.discountgeneral()) / 100) })
            return totalDisc;
        });
        self.grandTotalTVA = ko.pureComputed(function () {
            var totalTVA = 0;
            $.each(self.lines(), function () { totalTVA += this.PriceHT() * parseFloat("0" + self.tva().Pourcentage) / 100 })
            return totalTVA;
        });
        self.grandTotal = ko.pureComputed(function () {
            var total = 0;
            $.each(self.lines(), function () { total += this.PriceHT() - (this.PriceHT() * parseFloat("0" + self.discountgeneral()) / 100) + (this.PriceHT() * parseFloat("0" + self.tva().Pourcentage) / 100) })
            return total;
        });


        // Operations
        self.addDetail = function () {
            self.lines.push(new QuotationDetail())
        };
        self.removeDetail = function (line) { self.lines.remove(line) };

    };



    $(document).ready(function () {
        ko.applyBindings(new Quotation());
    });

我的编辑器模板视图

<div class="detail">
    <div class="row" data-bind="ifnot: ProductName">
        <div class="form-group col-md-6">
            <label>Catégorie</label>
            <select class="form-control" data-bind="options: productCategories, optionsText: 'Title',optionsCaption: 'Catégorie...', value: ProductCategory"> </select>
        </div>
        <div class="form-group col-md-6" data-bind="with:ProductCategory">
            <label>Produit</label>
            <select class="form-control" data-bind="options : Products,optionsText: 'Title',optionsCaption: 'Produit...',value:$parent.Product"> </select>

        </div>
        <div data-bind="with:Product">
           
            <input type="hidden" data-bind="value: Id, attr: {name: 'QuotationDetails[' + $index() + '].ProductId'}" />

        </div>
    </div>
    <div class="form-row">
        <div class="form-group col-md-2">
            <label>Type</label>
            @Html.EnumDropDownListFor(model => model.UniteQuotation, new { data_bind = "value : UniteQuotation", @class = "form-control", placeholder = "Type" })
        </div>

        <div class="form-group col-md-4">
            <label>Produit</label>
            @Html.TextBoxFor(model => model.ProductName, new { data_bind = "text:ProductName", @class = "form-control", @readonly = "readonly"  })
    
        </div>
        <div class="form-group col-md-1">

            <h5> Quantité <span class="text-danger">*</span></h5>
            <div class="controls">
                @Html.TextBoxFor(model => model.Quantity, new
                {
                    data_bind = "textInput :Quantity,valueUpdate:'afterkeydown'",
                    @class = "form-control",
                    required = "required",
                    data_validation_required_message = "Veuillez renseigner une quantité"
                })

            </div>
        </div>

        <div class="form-group col-md-2">

            <h5> Prix unitaire <span class="text-danger">*</span></h5>
            <div class="controls">

                @Html.TextBoxFor(model => model.PriceUnit, new { data_bind = "textInput:PriceUnit,valueUpdate: 'afterkeydown'", @class = "form-control", required = "required", data_validation_required_message = "Veuillez renseigner un prix unitaire" })

            </div>
        </div>


        <div class="form-group col-md-1">
            <label>Remise (%)</label>
            @Html.TextBoxFor(model => model.Discount,
                                                        new { data_bind = "textInput: Discount", @class = "form-control" })
        </div>
        <div class="form-group col-md-1">
            <label>Total HT</label>
            € @Html.TextBoxFor(model => model.PriceHT, new { data_bind = "value:formatCurrencyDouble(PriceHT())", @class = "form-control", @readonly = "readonly" })

        </div>

        <div class="form-group col-md-1">
            <label></label>
            <a href='#' data-bind='click: $parent.removeDetail'><i class="far fa-times-circle" style="font-size:40px"></i></a>

        </div>
    </div>
    <div class="form-group col-md-12">
        @Html.TextAreaFor(model => model.Description, new { data_bind = "value:Description , summernote: { height: 250 },valueUpdate: 'afterkeydown'", rows = "10", @class = "form-control summernote", placeholder = "Description" })
        @Html.ValidationMessageFor(model => model.Description, "", new { @class = "text-danger" })

    </div>


</div>

我已经疯了两个星期了。你能帮我吗?

标签: asp.net-mvcrazorknockout.jsknockout-mapping-plugin

解决方案


推荐阅读