多个tagit和knockout.js

时间:2016-04-06 16:16:03

标签: razor knockout.js tag-it

我正在尝试创建一个用户可以添加多个产品的页面,每个产品可以有多个竞争对手。竞争对手的作品需要使用tagit生成。由于某种原因,tagit无法正常工作...... 这是淘汰赛模板:

<script type="text/html" id="product-template">
<tr>
    <td style="width: 5%">
        <input type="hidden" name="Products.Index" data-bind="value: Id"/>
    </td>
    <td style="width: 30%">
        Product:<br/>
        <select data-bind='options: ProductSource, optionsText: "Product", optionsCaption: "", value: Product, attr: { name: "Products[" + Id + "].Product" }'></select>
    </td>
    <td style="width: 30%; line-height: 100%; margin-top: 0; padding-top: 0">
        Competitors:<br/>
        <div id="tags_error" style="display: none;" class="ui-state-error-text">entries must be less than 50 characters each</div>
        <ul class="tags" style="margin-top: 2px; padding-top: 0" data-bind="foreach: Competitors">
            <li data-bind="text: $data" >
            </li >
        </ul>
        <div style="font-size: 10px; color: GrayText; font-style: italic;">please separate tags using the comma or enter key</div>
        @* <input type="text" value="" data-bind='attr: { name: "Products[" + $parent.Id + "].Competitors" }' />*@
    </td>
    <td style="width: 30%">
        Positioning:<br/>
        <select data-bind='options: PositioningSource, optionsText: "Positioning", optionsCaption: "", value:Positioning, attr: { name: "Products[" + Id + "].Positioning" }'></select>
    </td>
    <td style="width: 5%">
        <a href="#" data-bind="click: $parent.removeProduct">
            <img src="@Links.Content.Images.DeleteAlert_gif"/>
        </a>
    </td>
</tr>

这是我的淘汰模型视图:

 $(document).ready(function () {

    function ProductItem(id, product, positioning, competitors) {
        var self = this;
        self.Id = id;
        self.Product = ko.observable(product);
        self.Positioning = ko.observable(positioning);
        self.Competitors = ko.observableArray(competitors);
        self.Competitors.push( '1', '2', '3' );
        self.errors = ko.validation.group(self);
    }

    function ProductsViewModel() {
        var self = this;
        var id = 0;
        self.Products = [];
        self.Products = ko.observableArray();

        @if (Model.Products != null)
        {
            foreach (var item in Model.Products)
            {
                <text>self.Products.push(new ProductItem(id++, '@item.Product', '@item.Positioning', '@item.Competitors'));</text>
            }
        }

        self.selectedProduct = ko.observable();
        self.addProduct = function () {
            self.Products.push(new ProductItem(id++));
        };
        self.removeProduct = function (product) {
            self.Products.remove(product);
        };
    }
    ko.validation.init({ insertMessages: true, decorateElement: true, errorClass: "error" });
    ko.applyBindingsWithValidation(new ProductsViewModel());
});

这是标签设置:

  $(function () {
    var changed = function (e1, e2) {
        var item = $(e2);
        if (item.find('input').val().length > 50) {
            setTimeout(function () { item.remove(); }, 50);
            $('#tags_error').show();
            setTimeout(function () { $('#tags_error').fadeOut(1000); }, 10000);
        } else {
            $('.tags, .tags input').addClass('ui-state-highlight');
        }
    };
    $('.tags').tagit({
        tagSource: '@Html.Raw(Url.Action(MVC.Marketing.Campaign.SearchTags()))',
        removeConfirmation: true,
        allowSpaces: true,
        caseSensitive: false,
        onTagAdded: changed,
        onTagRemoved: changed,
        placeholderText: 'enter a tag'
    });
});

添加产品效果很好,只是竞争对手显示为列表而不是输入,我可以添加标签......

1 个答案:

答案 0 :(得分:0)

解决方案。模板:

<script type="text/html" id="product-template">
<tr>
    <td style="width: 5%">
        <input type="hidden" name="Products.Index" data-bind="value: Id"/>
    </td>
    <td style="width: 30%">
        Product:<br/>
        <select data-bind='options: ProductSource, optionsText: "Product", optionsCaption: "", value:Product'></select>
        <input data-bind='attr: { name: "Products[" + Id + "].Product", value: (Product() !== undefined) ? Product().Product : "" }' type="hidden" value="">
    </td>
    <td style="width: 30%; line-height: 100%; margin-top: 0; padding-top: 0">
        Competitors:<br/>
        <ul style="margin-top: 2px; padding-top: 0" data-bind="tagit:Competitors, productId:$data.Id"></ul>
        <div style="font-size: 10px; color: GrayText; font-style: italic;">please separate competitors using the comma or enter key</div>
    </td>
    <td style="width: 30%">
        Positioning:<br/>
        <select data-bind='options: PositioningSource, optionsText: "Positioning", optionsCaption: "", value:Positioning'></select>
        <input data-bind='attr: { name: "Products[" + Id + "].Positioning", value: (Positioning() !== undefined) ? Positioning().Positioning : "" }' type="hidden" value="">
    </td>
    <td style="width: 5%">
        <a href="#" data-bind="click: $parent.removeProduct">
            <img src="@Links.Content.Images.DeleteAlert_gif"/>
        </a>
    </td>
</tr>

淘汰赛模特:

<script type="text/javascript">
var ProductSource = [];
var index = 0;
$.ajax({
    type: "GET",
    url: '@Html.Raw(Url.Action(MVC.UserChoice.ForName()))',
    data: { userChoiceName: '@UserChoiceKey.OpportunityProductInterest' },
    cache: false,
    success: function (data) {
        data.forEach(function (item)
        { ProductSource.push({ Product: item.Text }); });
    }
});

var PositioningSource = [];
var index = 0;
$.ajax({
    type: "GET",
    url: '@Html.Raw(Url.Action(MVC.UserChoice.ForName()))',
    data: { userChoiceName: '@UserChoiceKey.WorkRequestProductPositioning' },
    cache: false,
    success: function (data) {
        data.forEach(function (item)
        { PositioningSource.push({ Positioning: item.Text }); });
    }
});

$(document).ready(function () {

    function ProductItem(id, product, positioning, competitors) {
        var self = this;
        self.Id = id;
        self.Product = ko.observable(product);
        self.Positioning = ko.observable(positioning);
        self.Competitors = ko.observableArray(competitors);
        self.errors = ko.validation.group(self);
    }

    function ProductsViewModel() {
        var self = this;
        var id = 0;
        self.Products = [];
        self.Products = ko.observableArray();

        @if (Model.Products != null)
        {
            foreach (var item in Model.Products)
            {
                <text>self.Products.push(new ProductItem(id++, '@item.Product', '@item.Positioning', '@item.Competitors'));</text>
            }
        }

        self.selectedProduct = ko.observable();
        self.addProduct = function () {
            self.Products.push(new ProductItem(id++));
        };
        self.removeProduct = function (product) {
            self.Products.remove(product);
        };
    }

    ko.bindingHandlers.tagit = {
        //https://github.com/aehlke/tag-it
        init: function (element, valueAccessor, allBindingsAccessor) {

            var options = {
                allowSpaces: true,
                caseSensitive: false,
                showAutocompleteOnFocus: true,
                tagSource: '@Html.Raw(Url.Action(MVC.Marketing.Campaign.SearchTags()))',
                itemName: "Products[" + allBindingsAccessor.get('productId') + "].Competitors",
                fieldName:""
            };

            var tags = allBindingsAccessor()["tagsSource"];
            if (tags)
                $.extend(options, {
                    autocomplete: { source: tags, delay: 0, minLength: 0 }
                });
            $(element).tagit(options);
        },
        update: function (element, valueAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor());
            var tags = value;

            $(element).tagit("removeAll");
            for (var x = 0; x < tags.length; x++) {
                $(element).tagit("createTag", tags[x]);
            }
        }
    };

    ko.validation.init({ insertMessages: true, decorateElement: true, errorClass: "error" });
    ko.applyBindingsWithValidation(new ProductsViewModel());
});