【问题标题】:Creating a autocomplete field with Typeahead in the Durandal Framework在 Durandal 框架中使用 Typeahead 创建自动完成字段
【发布时间】:2013-04-18 04:38:48
【问题描述】:

我正在尝试使用预先输入(twitter 引导程序)实现自动完成输入字段。这个自动完成字段应该是模态的,但我似乎无法让它工作!它还必须是可通过剔除观察到的,因为当您选择一个值时,其他字段应更新为。

所以我有点想在模态中做到这一点!

HTML

<div class="messageBox">
    <div class="modal-header">
        <h2>Adding a repairline</h2>
    </div>
    <div class="modal-body" style="width: 35em;">
        <form data-bind="submit: ok">
            <fieldset>
                <!--<legend></legend> Deze niet toevoegen uitlijning is dan niet goed!-->
                <div class="row-fluid">
                    <div class="span6">
                        <div>   
                            <label>
                                Description:
                                <input type="text" id="testen" data-provide="typeahead" />



                            </label>
                        </div>
                        <div>
                            <label>
                                Code:
                                <input data-bind="value: Code" required />
                            </label>
                        </div>          
                <div>
                    <input class="btn btn-primary" type="submit" value="Add" />
                </div>
            </fieldset>
        </form>
    </div>
    <div class="modal-footer">
        <button class="btn" data-bind="click: closeModal">Cancel</button>    
    </div>
</div>

JS

define(function (require) {
    var dataservice = require('services/dataservice'),
        allCustomers = ko.observableArray([]),
        repairlines = ko.observableArray([]);


    function init() {
        dataservice = new dataservice('api/data');
        dataservice.getAllRows('AllCustomers').then(function (data) {
            data.results.forEach(function (item) {
                allCustomers.push(item);
            });
        }).fail(function () {   
        });

        dataservice.getAllRows('EntireRepairLineLib').then(function (data) {
            data.results.forEach(function (item) {
                repairlines.push(item);
            });
        }).fail(function () {
        });

        $('.testen .typeahead').typeahead({
            name: 'countries',
            prefetch: 'http://twitter.github.io/typeahead.js/data/countries.json',
            limit: 10
        });
    }

    init();

    AddRepairOrderLineModal = function (loggedInEmployee) {
        //later ook customer en repairorder meegeven!
        this.allCustomers = allCustomers;
        this.choosenCustomerId = ko.observable(); //holds the Id of the chosen customer
        this.Description = ko.observable();
        this.Code = ko.observable();
        this.Mat = ko.observable();
        this.Location = ko.observable();
        this.Rep = ko.observable();
        this.Dum = ko.observable();
        this.Dam = ko.observable();
        this.Qty = ko.observable();
        this.Hours = ko.observable();
        this.Tariff = ko.observable();
        this.Costs = ko.observable();
        this.CreationDate = (new Date().getMonth() + 1) + "-" + new Date().getDate() + "-" + new Date().getFullYear();

        this.IsAgreement = ko.observable(true);
        this.IsAuthorized = ko.observable(true);
        this.DoRepair = ko.observable(true);
        this.selectedEmployee = loggedInEmployee;

       /* $(".repairlinename").autocomplete({
           source: repairlines 
        });*/


        $(document).ready(function() {
            alert('done');
            $('#testen').append(' Leroy');
        }); 
    };
    AddRepairOrderLineModal.prototype.ok = function () {
        var jsonObj = [];
        jsonObj.push({
            Description: this.Description(), Code: this.Code(),
            Mat: this.Mat(), Location: this.Location(),
            Rep: this.Rep(), Dum: this.Dum(), Dam: this.Dam(),
            CustomerId: this.choosenCustomerId(), Qty: this.Qty(), Hours: this.Hours(),
            Tariff: this.Tariff(), Costs: this.Costs(), CreationDate: this.CreationDate,
            IsAgreement: this.IsAgreement(), IsAuthorized: this.IsAuthorized(), DoRepair: this.DoRepair(),
        });
        this.modal.close(jsonObj);
    };

    AddRepairOrderLineModal.prototype.closeModal = function () {
        return this.modal.close();
    };
    return AddRepairOrderLineModal;
});



    /*define(['durandal/app','services/dataservice'], function(app,dataservice) {
        AddRepairOrderLineModal = function (loggedInEmployee) {
            //later ook customer en repairorder meegeven!




            this.Description = ko.observable();
            this.Code = ko.observable();
            this.Mat = ko.observable();
            this.Location = ko.observable();
            this.Rep = ko.observable();
            this.Dum = ko.observable();
            this.Dam = ko.observable();
            this.Customer = ko.observable();
            this.Qty = ko.observable();
            this.Hours = ko.observable();
            this.Tariff = ko.observable();
            this.Costs = ko.observable();
            this.CreationDate = (new Date().getMonth() + 1) + "-" + new Date().getDate() + "-" + new Date().getFullYear();

            this.IsAgreement = ko.observable(true);
            this.IsAuthorized = ko.observable(true);
            this.DoRepair = ko.observable(true);
            this.selectedEmployee = loggedInEmployee;
        };

        AddRepairOrderLineModal.prototype.ok = function () {
            var jsonObj = [];
            jsonObj.push({
                Description: this.Description(), Code: this.Code(),
                Mat: this.Mat(), Location: this.Location(),
                Rep: this.Rep(), Dum: this.Dum(), Dam: this.Dam(),
                Customer: this.Customer(), Qty: this.Qty(), Hours: this.Hours(),
                Tariff: this.Tariff(), Costs: this.Costs(), CreationDate: this.CreationDate,
                IsAgreement: this.IsAgreement(), IsAuthorized: this.IsAuthorized(), DoRepair: this.DoRepair()
            });
            this.modal.close(jsonObj);
        };

        AddRepairOrderLineModal.prototype.closeModal = function() {
            return this.modal.close();
        };
        return AddRepairOrderLineModal;
        /*
        http://stackoverflow.com/questions/7537002/autocomplete-combobox-with-knockout-js-template-jquery
        http://jsfiddle.net/rniemeyer/PPsRC/
        *//*
    });

    */

我希望有人可以帮助我如何做到这一点!来源是repairlines,这些都填对了

【问题讨论】:

    标签: javascript twitter-bootstrap knockout.js durandal


    【解决方案1】:

    您需要将预先输入的输入绑定到视图模型上公开的数组。我认为你目前都没有这样做。

    要进行绑定,您应该使用此处找到的敲除引导绑定: http://billpull.github.io/knockout-bootstrap/

    一旦你包含了上面的敲除引导绑定,你就可以在你的视图中这样做:

    <input type="text" data-bind="typeahead: repairlines" />
    

    然后确保您正在向您的虚拟机实例添加维修线。将它添加到您的 this 参考应该可以解决问题。

    // this will add the repairlines observable array to your VM instance
    this.repairlines = repairlines;
    

    希望这会有所帮助并祝你好运:-)

    【讨论】:

    • 我的第一个想法是这样可以解决问题,但事实并非如此 :( 我相信这与 Durandal 框架中的模态生命周期有关!
    • 抱歉没有正确阅读您的答案 XD,问题是我的项目中没有包含 Knockout-bootstrap javascript :) 现在一切正常 :)
    • 我还有一件事,维修线都是对象,我该怎么做?
    • 看起来你必须将 typeahead 控件绑定到一个字符串数组,然后如果需要进行查找以将你的对象返回到更新程序函数中,就像在这篇文章中一样。 deanhume.com/Home/BlogPost/…
    • 当我包含了淘汰赛引导程序时,我该怎么做? data-bind="typeahead: source" 但是我如何给它一个函数作为源呢?还有知道如何添加 minlength 吗?
    【解决方案2】:

    我会发表评论,但不能,所以这是我的笔记。在您的示例中,您有同源策略 (SOP) 问题。所以来自 twitter 页面的数据不会被拉进来。这几乎会扼杀这个过程,所以你不会得到任何东西。

    我发现如果我包含适当的样式(例如用于 tt-dropdown-menu 的样式):

    <span class="tt-dropdown-menu" style="position: absolute; top: 100%; left: 0px; z-index: 100; display: block; right: auto;"></span>
    

    并且拥有一个正常工作的数据集。这是我尝试http://jsfiddle.net/rUdXt/ 的一个小技巧,这是一个对我有帮助的很棒的页面(尤其是样式http://twitter.github.io/typeahead.js/examples/)。

    【讨论】:

    • 感谢您的提琴和示例,但它也不能解决问题;(如果它是一个普通页面,它会但在我的模式中它只是不起作用
    【解决方案3】:

    我已通过向库中添加一些额外代码来解决此问题:https://github.com/billpull/knockout-bootstrap

    这是 knockout-bootstrap.js,其中 ko.bindingHandlers.typeahead 被重写,因此它接受更新,minLength 项。只需加载此脚本即可。

    //UUID
    function s4() {
        return Math.floor((1 + Math.random()) * 0x10000)
            .toString(16)
            .substring(1);
    }
    
    function guid() {
        return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
    }
    
    // Outer HTML
    (function($){
      $.fn.outerHtml = function() {
        if (this.length == 0) return false;
        var elem = this[0], name = elem.tagName.toLowerCase();
        if (elem.outerHTML) return elem.outerHTML;
        var attrs = $.map(elem.attributes, function(i) { return i.name+'="'+i.value+'"'; }); 
        return "<"+name+(attrs.length > 0 ? " "+attrs.join(" ") : "")+">"+elem.innerHTML+"</"+name+">";
      };
    })(jQuery);
    
    // Bind twitter typeahead
    ko.bindingHandlers.typeahead = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            var $element = $(element);
            var allBindings = allBindingsAccessor();
            var typeaheadArr = ko.utils.unwrapObservable(valueAccessor());
    
            $element.attr("autocomplete", "off")
                    .typeahead({
                        'source': typeaheadArr,
                        'minLength': allBindings.minLength,
                        'items': allBindings.items,
                        'updater': allBindings.updater
                    });
        }
    };
    
    /*
    ko.bindingHandlers.typeahead = {
        init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    
    
            var $element = $(element);
            var t = valueAccessor();
            var typeaheadArr = ko.utils.unwrapObservable(valueAccessor());
            var k = allBindingsAccessor().v1;
    
            $element.attr("autocomplete", "off")
                    .typeahead({
                        'source' : typeaheadArr
                    });
        }
    };
    */
    
    // Bind Twitter Progress
    ko.bindingHandlers.progress = {
        init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            var $element = $(element);
    
            var bar = $('<div/>', {
                'class':'bar',
                'data-bind':'style: { width:' + valueAccessor() + ' }'
            });
    
            $element.attr('id', guid())
                .addClass('progress progress-info')
                .append(bar);
    
            ko.applyBindingsToDescendants(viewModel, $element[0]);
        }
    }
    
    // Bind Twitter Alert
    ko.bindingHandlers.alert = {
        init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            var $element = $(element);
            var alertInfo = ko.utils.unwrapObservable(valueAccessor());
    
            var dismissBtn = $('<button/>', {
                'type':'button',
                'class':'close',
                'data-dismiss':'alert'
            }).html('&times;');
    
            var alertMessage = $('<p/>').html(alertInfo.message);
    
            $element.addClass('alert alert-'+alertInfo.priority)
                    .append(dismissBtn)
                    .append(alertMessage);
        }
    };
    
    // Bind Twitter Tooltip
    ko.bindingHandlers.tooltip = {
        init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            // read tooltip options
            var tooltipBindingValues = ko.utils.unwrapObservable(valueAccessor());
    
            // set tooltip title
            var tooltipTitle = tooltipBindingValues.title;
    
            // set tooltip placement
            var tooltipPlacement = tooltipBindingValues.placement;
    
            // set tooltip trigger
            var tooltipTrigger = tooltipBindingValues.trigger;
    
            var options = {
                title: tooltipTitle
            };
    
            ko.utils.extend(options, ko.bindingHandlers.tooltip.options);
    
            if (tooltipPlacement) {
                options.placement = tooltipPlacement;
            }
    
            if (tooltipTrigger) {
                options.trigger = tooltipTrigger;
            }
    
            $(element).tooltip(options);
        },
        options: {
            placement: "top",
            trigger: "hover"
        }
    };
    
    // Bind Twitter Popover
    ko.bindingHandlers.popover = {
        init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            // read popover options 
            var popoverBindingValues = ko.utils.unwrapObservable(valueAccessor());
    
            // set popover title 
            var popoverTitle = popoverBindingValues.title;
    
            // set popover template id
            var tmplId = popoverBindingValues.template;
    
            // set popover trigger
            var trigger = 'click';
    
            if (popoverBindingValues.trigger) {
                trigger = popoverBindingValues.trigger;
            }
    
            // update triggers
            if (trigger === 'hover') {
                trigger = 'mouseenter mouseleave';
            } else if (trigger === 'focus') {
                trigger = 'focus blur';
            }
    
            // set popover placement
            var placement = popoverBindingValues.placement;
    
            // get template html
            var tmplHtml = $('#' + tmplId).html();
    
            // create unique identifier to bind to
            var uuid = guid();
            var domId = "ko-bs-popover-" + uuid;
    
            // create correct binding context
            var childBindingContext = bindingContext.createChildContext(viewModel);
    
            // create DOM object to use for popover content
            var tmplDom = $('<div/>', {
                "class" : "ko-popover",
                "id" : domId
            }).html(tmplHtml);
    
            // set content options
            options = {
                content: $(tmplDom[0]).outerHtml(),
                title: popoverTitle
            };
    
            if (placement) {
                options.placement = placement;
            }
    
            // Need to copy this, otherwise all the popups end up with the value of the last item
            var popoverOptions = $.extend({}, ko.bindingHandlers.popover.options, options);
    
            // bind popover to element click
            $(element).bind(trigger, function () {
                var popoverAction = 'show';
                var popoverTriggerEl = $(this);
    
                // popovers that hover should be toggled on hover
                // not stay there on mouseout
                if (trigger !== 'click') {
                    popoverAction = 'toggle';
                }
    
                // show/toggle popover
                popoverTriggerEl.popover(popoverOptions).popover(popoverAction);
    
                // hide other popovers and bind knockout to the popover elements
                var popoverInnerEl = $('#' + domId);
                $('.ko-popover').not(popoverInnerEl).parents('.popover').remove();
    
                // if the popover is visible bind the view model to our dom ID
                if($('#' + domId).is(':visible')){
                    ko.applyBindingsToDescendants(childBindingContext, $('#' + domId)[0]);
                }
    
                // bind close button to remove popover
                $(document).on('click', '[data-dismiss="popover"]', function (e) {
                    popoverTriggerEl.popover('hide');
                });
            });
    
            // Also tell KO *not* to bind the descendants itself, otherwise they will be bound twice
            return { controlsDescendantBindings: true };
        },
        options: {
            placement: "right",
            title: "",
            html: true,
            content: "",
            trigger: "manual"
        }
    };
    

    在您的 HTML 中执行此操作。

    <input type="text" data-bind="typeahead: repairlines(), minLength: 2, updater: updateViewAfterSelection, value: Description" required/>
    

    这是我的视图模型:

    define(function (require) {
        var dataservice = require('services/dataservice'),
            allCustomers = ko.observableArray([]),
            repairlinesRaw = ko.observableArray([]),
            Description = ko.observable(),
            InternalCode = ko.observable(),
            Mat = ko.observable(),
            Location = ko.observable(),
            Rep = ko.observable(),
            Dum = ko.observable(),
            Dam = ko.observable(),
            Qty = ko.observable(0).extend({ numeric: 2 }),
            Hours = ko.observable(0).extend({ numeric: 2 }),
            Tariff = ko.observable(0).extend({ numeric: 2 }),
            Costs = ko.observable(0).extend({ numeric: 2 });
    
        function init() {
            dataservice = new dataservice('api/data');
            dataservice.getAllRows('AllCustomers').then(function (data) {
                data.results.forEach(function (item) {
                    allCustomers.push(item);
                });
            }).fail(function () {
            });
    
            dataservice.getAllRows('EntireRepairLineLib').then(function (data) {
                data.results.forEach(function (item) {
                    repairlinesRaw.push(item);
                });
            }).fail(function () {
            });
        }
    
        init();
    
        AddRepairOrderLineModal = function (loggedInEmployee) {
            //later ook customer en repairorder meegeven!
            this.allCustomers = allCustomers;
            this.choosenCustomerId = ko.observable(); //holds the Id of the chosen customer
            this.Description = Description;
            this.InternalCode = InternalCode;
            this.Mat = Mat;
            this.Location = Location;
            this.Rep = Rep;
            this.Dam = Dam;
            this.Qty = Qty;
            this.Hours = Hours;
            this.Tariff = Tariff;
            this.Costs = Costs;
            //this.CreationDate = (new Date().getMonth() + 1) + "-" + new Date().getDate() + "-" + new Date().getFullYear();
            this.repairlines = function () {
                var repairlinesName = [];
                map = {};
                var data = repairlinesRaw();
                $.each(data, function (i, repairline) {
                    map[repairline.Description()] = repairline;
                    repairlinesName.push(repairline.Description());
                });
                return repairlinesName;
            };
    
            this.IsAgreement = ko.observable(true);
            this.IsAuthorized = ko.observable(true);
            this.DoRepair = ko.observable(true);
            this.selectedEmployee = loggedInEmployee;
        };
    
        AddRepairOrderLineModal.prototype.updateViewAfterSelection = function(item) {
            //map can be found in the repairlines function
            Description(map[item].Description());
            InternalCode(map[item].InternalCode());
            Mat(map[item].MaterialCode());
            Location(map[item].LocationCode());
            Rep(map[item].RepairCode());
            Dam(map[item].DamageCode());
            Qty(map[item].Quantity());
            Hours(map[item].Hours());
            Costs(map[item].Costs());
            return item;
        };
    
        AddRepairOrderLineModal.prototype.ok = function () {
            var jsonObj = [];
            jsonObj.push({
                Description: this.Description(), InternalCode: this.InternalCode(),
                Mat: this.Mat(), Location: this.Location(),
                Rep: this.Rep(), Dam: this.Dam(),
                CustomerId: this.choosenCustomerId(), Qty: this.Qty(), Hours: this.Hours(),
                Tariff: this.Tariff(), Costs: this.Costs(),
                IsAgreement: this.IsAgreement(), IsAuthorized: this.IsAuthorized(), DoRepair: this.DoRepair(),
            });
    
            //empty all fields after JSON 
            //Otherwise the values would still be there when a new modal is opened again.
            Description(null);
            InternalCode(null);
            Mat(null);
            Location(null);
            Rep(null);
            Dum(null);
            Dam(null);
            Qty(0);
            Hours(0);
            Tariff(0);
            Costs(0);
    
            this.modal.close(jsonObj);
        };
    
        AddRepairOrderLineModal.prototype.closeModal = function () {
            return this.modal.close();
        };
        return AddRepairOrderLineModal;
    });
    

    希望人们能理解这一点 ;),希望它有所帮助,很多功劳归于 Bill Pull ;) 和 Alex Preston

    【讨论】:

      【解决方案4】:

      无法理解,因为它太混乱了。也就是说,预输入位与所有其他内容混合在一起。 一个简单的例子呢

      那么我们就有机会了解它了

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-30
        • 2013-03-15
        • 2016-06-08
        相关资源
        最近更新 更多