2015-07-14 1 views
16

Я столкнулся с этой проблемой, и я не знаю, как ее решить. Я использовал ui-select multiselect на своей странице. Во-первых, запрос http.get делается на URL-адрес, который получает данные, затем выбираются варианты выбора ui-select. Данные большие - длина данных составляет 2100. Эти данные должны отображаться как выбор. (Данные извлекаются в начале во время загрузки страницы и сохраняются в массиве)ui-select multiselect очень медленно отображает выбор

Но проблема в том, что каждый раз, когда я нажимаю на мультиселектор, чтобы выбрать выбор, требуется 4-5 секунд для заполнения список, и страница становится очень медленной. Что мне делать, чтобы уменьшить это время?

Данные выбора хранятся в массиве, тип данных - это массив строк.

<ui-select multiple ng-model="selectedFields.name" style="width: 100%;"> 
    <ui-select-match placeholder="Select fields...">{{$item}}</ui-select-match> 
    <ui-select-choices repeat="fields in availableFields | filter:$select.search"> 
     {{fields}} 
    </ui-select-choices> 
    </ui-select> 

в контроллере,

$scope.selectedFields = {}; 
$scope.selectedFields.name = []; 

$scope.init = function() { 

    $http.get(url) 
     .success(function(response, status, headers, config) { 
      availableFields = response; 
     }) 
     .error(function(err) { 
     }); 
}; 

$scope.init(); 

Если не так, то есть ли другие варианты/выбор я могу работать с которой не задержит показывая Select-выбор?

ответ

13

Это известная проблема в ui-select. Я попытался следующие способы, как работают

1) Существует обходной путь для этого - использовать

| limitTo: 100 

Это ограничивает отображение выбора до 100, но все варианты могут быть выбраны. Посмотрите на this thread для более подробной информации.

2) С некоторого времени необходимо отобразить весь список в вариантах, 1) не является жизнеспособным вариантом. Я использовал другую библиотеку - selectize.js. Вот демо-версия plunker, приведенная на странице

4

Как указано, ui-select имеет немало проблем с производительностью, но есть проблема с решением проблемы с лимитом.

Если вы будете следовать подходу akashrajkn, тогда вы заметите, что он фактически вырезает важные фрагменты данных, поскольку он будет отображать только 100 за раз. Eсть фикса, который прошел модульные тесты и может быть найден на резьбе тута:

https://github.com/angular-ui/ui-select/pull/716

В принципе, если вы храните яваскрипт файл локально, тогда вы можете настроить unminified версию. Все, что вам нужно сделать, это реализовать изменения, внесенные им в запрос на растяжение, и это должно значительно помочь. Для того, чтобы применить лимитирующий фактор, посмотрите на ниже, модифицированный примере:

<ui-select multiple ng-model="selectedFields.name" limit = "10" style="width: 100%;"> 
    <ui-select-match placeholder="Select fields...">{{$item}}</ui-select-match> 
    <ui-select-choices repeat="fields in availableFields | filter:$select.search | limitTo:$select.limit "> 
     {{fields}} 
    </ui-select-choices> 
</ui-select> 

выше будет ограничивать ваши данные в раскрывающемся в том же время поддерживая уровень согласованности необходимо.

+0

Я пробовал это, но он по-прежнему создает ту же проблему, отображение выбора занимает почти 5 секунд каждый раз, и в течение этого времени страница становится невосприимчивой – akashrajkn

+0

Правильно, и это произойдет из-за проблем с производительностью с ui- Выбрать. Единственный способ - фактически зайти в файл и удалить большинство бесполезных кодов, которые сосредоточены вокруг событий keydown/keyup (бесполезно, если вы им не нужны, конечно). Существуют и другие плагины select2 для угловых, но похоже, что они не поддерживаются в ui-select. И, конечно же, вы всегда можете попытаться переписать требуемую функциональность. – BuddhistBeast

+0

отображает только 10, но показывает в поиске –

6

Это полное решение, которое украшает директиву uiSelectChoices.

Элементы заполняются постепенно, когда пользователь прокручивает.

Также занимается поиском в свитках.

Также работает для всех значений position={auto, up, down}

Пример

<ui-select-choices 
     position="up" 
     all-choices="ctrl.allTenThousandItems" 
     refresh-delay="0" 
     repeat="person in $select.pageOptions.people | propsFilter: {name: $select.search, age: $select.search} "> 
     <div ng-bind-html="person.name | highlight: $select.search"></div> 
     <small> 
     email: {{person.email}} 
     age: <span ng-bind-html="''+person.age | highlight: $select.search"></span> 
     </small> 
    </ui-select-choices> 

Working Plnkr Также с With v0.19.5

дИРЕКТИВЫ

app.directive('uiSelectChoices', ['$timeout', '$parse', '$compile', '$document', '$filter', function($timeout, $parse, $compile, $document, $filter) { 
    return function(scope, elm, attr) { 
    var raw = elm[0]; 
    var scrollCompleted = true; 
    if (!attr.allChoices) { 
     throw new Error('ief:ui-select: Attribute all-choices is required in ui-select-choices so that we can handle pagination.'); 
    } 

    scope.pagingOptions = { 
     allOptions: scope.$eval(attr.allChoices) 
    }; 

    attr.refresh = 'addMoreItems()'; 
    var refreshCallBack = $parse(attr.refresh); 
    elm.bind('scroll', function(event) { 
     var remainingHeight = raw.offsetHeight - raw.scrollHeight; 
     var scrollTop = raw.scrollTop; 
     var percent = Math.abs((scrollTop/remainingHeight) * 100); 

     if (percent >= 80) { 
     if (scrollCompleted) { 
      scrollCompleted = false; 
      event.preventDefault(); 
      event.stopPropagation(); 
      var callback = function() { 
      scope.addingMore = true; 
      refreshCallBack(scope, { 
       $event: event 
      }); 
      scrollCompleted = true; 

      }; 
      $timeout(callback, 100); 
     } 
     } 
    }); 

    var closeDestroyer = scope.$on('uis:close', function() { 
     var pagingOptions = scope.$select.pagingOptions || {}; 
     pagingOptions.filteredItems = undefined; 
     pagingOptions.page = 0; 
    }); 

    scope.addMoreItems = function(doneCalBack) { 
     console.log('new addMoreItems'); 
     var $select = scope.$select; 
     var allItems = scope.pagingOptions.allOptions; 
     var moreItems = []; 
     var itemsThreshold = 100; 
     var search = $select.search; 

     var pagingOptions = $select.pagingOptions = $select.pagingOptions || { 
     page: 0, 
     pageSize: 20, 
     items: $select.items 
     }; 

     if (pagingOptions.page === 0) { 
     pagingOptions.items.length = 0; 
     } 
     if (!pagingOptions.originalAllItems) { 
     pagingOptions.originalAllItems = scope.pagingOptions.allOptions; 
     } 
     console.log('search term=' + search); 
     console.log('prev search term=' + pagingOptions.prevSearch); 
     var searchDidNotChange = search && pagingOptions.prevSearch && search == pagingOptions.prevSearch; 
     console.log('isSearchChanged=' + searchDidNotChange); 
     if (pagingOptions.filteredItems && searchDidNotChange) { 
     allItems = pagingOptions.filteredItems; 
     } 
     pagingOptions.prevSearch = search; 
     if (search && search.length > 0 && pagingOptions.items.length < allItems.length && !searchDidNotChange) { 
     //search 


     if (!pagingOptions.filteredItems) { 
      //console.log('previous ' + pagingOptions.filteredItems); 
     } 

     pagingOptions.filteredItems = undefined; 
     moreItems = $filter('filter')(pagingOptions.originalAllItems, search); 
     //if filtered items are too many scrolling should occur for filtered items 
     if (moreItems.length > itemsThreshold) { 
      if (!pagingOptions.filteredItems) { 
      pagingOptions.page = 0; 
      pagingOptions.items.length = 0; 
      } else { 

      } 
      pagingOptions.page = 0; 
      pagingOptions.items.length = 0; 
      allItems = pagingOptions.filteredItems = moreItems; 

     } else { 
      allItems = moreItems; 
      pagingOptions.items.length = 0; 
      pagingOptions.filteredItems = undefined; 
     } 


     } else { 
     console.log('plain paging'); 
     } 
     pagingOptions.page++; 
     if (pagingOptions.page * pagingOptions.pageSize < allItems.length) { 
     moreItems = allItems.slice(pagingOptions.items.length, pagingOptions.page * pagingOptions.pageSize); 
     } 

     for (var k = 0; k < moreItems.length; k++) { 
     pagingOptions.items.push(moreItems[k]); 
     } 

     scope.calculateDropdownPos(); 
     scope.$broadcast('uis:refresh'); 
     if (doneCalBack) doneCalBack(); 
    }; 
    scope.$on('$destroy', function() { 
     elm.off('scroll'); 
     closeDestroyer(); 
    }); 
    }; 
}]); 
+0

Привет, я попробовал это. оно работает. но у меня проблема. если я выберу элементы в 9k + ниже. выбор выбора ui больше не будет открыт. Какая может быть проблема? Спасибо – Binsoi

+0

http://plnkr.co/edit/oRmKRV?p=preview использует 9500 предметов. Вок хорошо. Можете ли вы воспроизвести модификацию этого plnkr? – bhantol

+0

Я попытался проверить ui-select и нашел div из опций opacity был установлен на 0. i проверил select_0_17.js и изменил эту строку с 0 на 1. // Сброс позиции выпадающего списка. # 1333 выпадающее меню [0] .style.opacity = 1; Я использую его в chrome app btw. – Binsoi

3

Потому что я не могу leav e комментарий (недостаточно rep) Я пишу это как ответ, и мне жаль, что это не ответ на проблему.

@bhantol Я изменил следующую строку кода в решение, которое отлично работает для меня до сих пор

for (var k = 0; k < moreItems.length; k++) { 
    pagingOptions.items.push(moreItems[k]); 
} 

for (var k = 0; k < moreItems.length; k++) { 
    if (pagingOptions.items.indexOf(moreItems[k]) == -1){ 
    pagingOptions.items.push(moreItems[k]); 
    } 
} 

Это предотвращает дублирующиеся элементы от просмотра, если пользователь начинает писать фильтр, а затем удаляет Это.

Кроме того, я просто понял, что если список меньше, чем 20 пунктов он не будет работать, поэтому я изменил:

if (pagingOptions.page * pagingOptions.pageSize < allItems.length) { 
    moreItems = allItems.slice(pagingOptions.items.length, pagingOptions.page * pagingOptions.pageSize); 
} 

к:

if (pagingOptions.page * pagingOptions.pageSize < allItems.length) { 
    moreItems = allItems.slice(pagingOptions.items.length, pagingOptions.page * pagingOptions.pageSize); 
} 
else{ moreItems = allItems;} 

Может быть, это поможет вам как-то и жаль снова за то, что не ответил на вопрос.

+0

@bhantol список не выбирает выделенный элемент, если значение ngModel передано из строки запроса. или Если пользователь нажимает кнопку «перезагрузить» страницу. 'person.id как человек в $ select.pageOptions.people' – Tawani

 Смежные вопросы

  • Нет связанных вопросов^_^