0

ui-selectとangle-touchの両方を使用するAngularJSアプリケーションで問題があります。ui-select入力がクリックに焦点を当てていない:angle-touchとの衝突

iPadやiPhoneなどのモバイルデバイスを使用しているSafariでは、ui-selectディレクティブのテキスト入力フィールドをクリックすると、仮想キーボードが開いていないため、入力にフォーカスが得られません。

私はアプリからの依存関係を取り除くとすべてが正常に機能するので、問題の原因となるのはアンカータッチだということを発見しました。

HTML

<body ng-controller="DemoCtrl"> 
    <ui-select multiple 
      theme="select2" 
      ng-model="multipleDemo.selection" 
      reset-search-input="true" 
      style="min-width: 300px;"> 
    <ui-select-match placeholder="Enter an adress..."> 
     {{$item.formatted_address}} 
    </ui-select-match> 
    <ui-select-choices repeat="address in addresses track by $index" 
         refresh="refreshAddresses($select.search)" 
         refresh-delay="250"> 
     <div ng-bind-html="address.formatted_address | highlight: $select.search"></div> 
    </ui-select-choices> 
    </ui-select> 
    <p>Selected : {{multipleDemo.selection | selectionFilter}}</p> 

</body> 

JS

var app = angular.module('demo', ['ngSanitize', 'ui.select', 'ngTouch']); 

app.filter('selectionFilter', function() { 
    // Not important... see the plunker for detail. 
}); 

app.controller('DemoCtrl', function($scope, $http) { 
    $scope.multipleDemo = {}; 
    $scope.multipleDemo.selection = []; 

    $scope.address = {}; 
    $scope.refreshAddresses = function(address) { 
    var params = {address: address, sensor: false}; 
    return $http.get(
     'http://maps.googleapis.com/maps/api/geocode/json', 
     {params: params} 
    ).then(function(response) { 
     $scope.addresses = response.data.results; 
    }); 
    }; 

}); 

http://plnkr.co/edit/dFBQ4si6hLMP1S9dal7m?p=preview

誰かが私が問題を引き起こしてからngTouchを防ぐために何ができるかのアイデアを持っていますか?依存関係からngTouchを削除することはできません:私はそれを他の場所で必要としています。

更新16/09

は、問題は、角度タッチ(1.4.8)のこの部分から来ているようだ:

element.on('touchend', function(event) { 
    var diff = Date.now() - startTime; 

    // Use jQuery originalEvent 
    var originalEvent = event.originalEvent || event; 
    var touches = (originalEvent.changedTouches && originalEvent.changedTouches.length) ? 
     originalEvent.changedTouches : 
     ((originalEvent.touches && originalEvent.touches.length) ? originalEvent.touches : [originalEvent]); 
    var e = touches[0]; 
    var x = e.clientX; 
    var y = e.clientY; 
    var dist = Math.sqrt(Math.pow(x - touchStartX, 2) + Math.pow(y - touchStartY, 2)); 

    if (tapping && diff < TAP_DURATION && dist < MOVE_TOLERANCE) { 
    // Call preventGhostClick so the clickbuster will catch the corresponding click. 
    preventGhostClick(x, y); 

    // Blur the focused element (the button, probably) before firing the callback. 
    // This doesn't work perfectly on Android Chrome, but seems to work elsewhere. 
    // I couldn't get anything to work reliably on Android Chrome. 
    if (tapElement) { 
     tapElement.blur(); 
    } 

    if (!angular.isDefined(attr.disabled) || attr.disabled === false) { 
     element.triggerHandler('click', [event]); 
    } 
    } 

    resetState(); 
}); 

私は条件を無効にした場合、例えば&& falseを追加し、入力はクリックに焦点を当てます。 私は、angle-touch libの外側の入力にこのイベントバインディングを無効にする方法を見つける必要があります。

答えて

3

以下のディレクティブ、ui-select親ディレクティブに適用されるが、この問題を解決:

app.directive('fixFocusOnTouch', function(){ 
    return { 
    restrict: 'A', 
    controller: function($element){ 
     /* 
     Usually, event handlers binding are made in the link function. 
     But we need this handler to be executed first, so we add it in the controller function instead. 
     */ 
     var inputElement = $element[0].querySelector('input.ui-select-search'); 
     angular.element(inputElement).bind('touchend', function(event){ 
     event.stopImmediatePropagation(); 
     }); 
    } 
    } 
}); 

角度ワンタッチで追加されたハンドラが実行できる前に、それはtouchendイベントの現在の伝播を殺す(「更新」を参照してください。質問の一部)。

私はPlunkrで動作させることができませんでしたが、もう一度試してみましょう。

使用法:

<ui-select multiple fix-focus-on-touch 
      theme="select2" 
      ng-model="multipleDemo.selection" 
      reset-search-input="true" 
      style="min-width: 300px;"> 
    <ui-select-match placeholder="Enter an adress..."> 
    {{$item.formatted_address}} 
    </ui-select-match> 
    <ui-select-choices repeat="address in addresses track by $index" 
        refresh="refreshAddresses($select.search)" 
        refresh-delay="250"> 
    <div ng-bind-html="address.formatted_address | highlight: $select.search"></div> 
    </ui-select-choices> 
</ui-select> 
関連する問題