문제

tl:dr

ajax/json을 사용하여 '선택' 필터를 포함하여 ng-table을 어떻게 채울 수 있나요?

문제를 보여주는 Plunk:http://plnkr.co/Zn09LV


세부 사항

나는 AngualrJS와 ng-table 확장을 이해하려고 노력하고 있습니다. 비록 작동하는 필터가 있는 멋진 테이블을 얻을 수 있지만 자바 스크립트에 정의된 정적 데이터를 사용할 때 - 일단 실제 데이터를 로드하려고 하면 내가 걸림돌을 쳤던 테이블.

ng-table의 본체가 올바르게 채워지고 텍스트 필터만 사용하는 한 모든 것이 작동하는 것 같습니다.

        <td data-title="'Name'" filter="{ 'Name': 'text' }" sortable="'Name'">
            {{user.Name}}
        </td>

잘 작동합니다.

그러나 선택 필터를 사용하도록 이를 업데이트하면 다음과 같습니다.

        <td data-title="'Name'" filter="{ 'Name': 'select' }" sortable="'Name'"  filter-data="Names($column)">
            {{user.Name}}
        </td>

데이터가 서버에서 반환되기 전에 Names 변수가 항상 평가된다는 점에서 동기화 문제가 발생합니다.(아마도 Names 변수는 서버에 대한 요청이 전송되기 전에 평가될 것입니다.) 이는 필터에 대한 빈 목록을 얻는다는 의미입니다.

서버에서 데이터가 반환되면 선택 필터를 업데이트하는 방법을 찾을 수 없는 것 같습니다.처음에는 필터 목록을 생성하는 코드를 다시 실행해도 아무런 효과가 없는 것 같습니다. 업데이트된 변수를 읽지 않도록 필터를 다시 확인하기 위해 ng-table을 트리거하는 방법을 잘 모르겠습니다.또한 비동기 호출이 완료될 때까지 변수 평가를 연기하는 방법을 찾을 수 없습니다.

내 자바스크립트의 경우 ng-table GitHub 페이지의 예제 Ajax 코드를 거의 사용하고 여기에 선택 필터의 예제 코드를 추가했습니다.

    $scope.tableParams = new ngTableParams({
        page: 1,            // show first page
        count: 10,          // count per page
        sorting: {
            name: 'asc'     // initial sorting
        }
    }, {
        total: 0,           // length of data
        getData: function($defer, params) {
            // ajax request to api
            Api.get(params.url(), function(data) {
                $timeout(function() {
                    // update table params
                    var orderedData = params.sorting ?
                    $filter('orderBy')(data.result, params.orderBy()) :
                    data.result;
                    orderedData = params.filter ?
                    $filter('filter')(orderedData, params.filter()) :
                    orderedData;

                    $scope.users = orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count());

                    params.total(orderedData.length); // set total for recalc pagination
                    $defer.resolve($scope.users);
                }, 500);
            });
        }
    });

    var inArray = Array.prototype.indexOf ?
    function (val, arr) {
        return arr.indexOf(val)
    } :
    function (val, arr) {
        var i = arr.length;
        while (i--) {
            if (arr[i] === val) return i;
        }
        return -1
    };
$scope.names = function(column) {
    var def = $q.defer(),
        arr = [],
        names = [];
    angular.forEach(data, function(item){
        if (inArray(item.name, arr) === -1) {
            arr.push(item.name);
            names.push({
                'id': item.name,
                'title': item.name
            });
        }
    });
    def.resolve(names);
    return def;
};

추가 $q.defer()를 추가하고 초기 데이터를 $scope.names 함수로 래핑하는 시도를 몇 번 시도했지만 약속과 연기에 대한 이해가 제대로 작동하지 않을 만큼 강력하지 않습니다.

GitHub에는 이것이 ng-table의 버그라고 제안하는 몇 가지 메모가 있지만 그것이 사실인지 아니면 그냥 멍청한 일을 하고 있는지 확실하지 않습니다.

https://github.com/esvit/ng-table/issues/186

진행 방법에 대한 조언을 주셔서 감사합니다.

-케인-

도움이 되었습니까?

해결책

비슷하지만 약간 더 복잡한 문제가 있었습니다.어쨌든 $scope 변수에 있어야 하기 때문에 완전히 실행 가능한 것처럼 보이는 필터 목록을 동적으로 업데이트할 수 있기를 원했습니다.기본적으로 나는 그럴 것이라고 예상했다. $scope.filterOptions = []; 그럼 내가 설정할 수있어 filter-data="filterOptions" 해당 목록에 대한 모든 업데이트는 자동으로 반영됩니다.내가 틀렸어.

그러나 나는 꽤 좋다고 생각하는 해결책을 찾았습니다.먼저 ngTable 선택 필터 템플릿을 재정의해야 합니다(이 작업을 수행하는 방법을 모르는 경우 $templateCache 재정의해야 할 키는 다음과 같습니다. 'ng-table/filters/select.html').

일반 템플릿에서는 다음과 같은 내용을 찾을 수 있습니다. ng-options="data.id as data.title for data in $column.data" 그리고 그 문제는 그거야 $column.data 업데이트할 때 변경되지 않는 고정 값입니다. $scope.filterOptions.

내 해결책은 $scope 만 전달하는 것입니다. 열쇠 전체 옵션 목록을 전달하는 대신 필터 데이터로 사용됩니다.그래서 대신에 filter-data="filterOptions", 나는 통과 할 것이다 filter-data="'filterOptions'" 그런 다음 템플릿에 다음과 같이 약간 변경합니다. ng-options="data.id as data.title for data in {{$column.data}}".

분명히 이것은 선택 필터의 작동 방식에 중요한 변화입니다.내 경우에는 테이블이 하나만 있는 아주 작은 앱에 대한 것이었지만 이와 같은 변경으로 인해 다른 선택이 중단될까 봐 걱정할 수도 있습니다.이 경우 'select'를 재정의하는 대신 이 솔루션을 사용자 지정 필터로 빌드할 수 있습니다.

다른 팁

당신은 그것을 달성할 수 있습니다 맞춤 필터:

그만큼 암호 ngtable의 표준 선택 필터에 대해 다음과 같이 말합니다.

<select ng-options="data.id as data.title for data in column.data"
    ng-model="params.filter()[name]"
    ng-show="filter == 'select'"
    class="filter filter-select form-control" name="{{column.filterName}}">
</select>

이 데이터를 호출하면 다음을 전달합니다. filter-data="names($column)" ngtable이 데이터 가져오기를 담당합니다.왜 이것이 외부 리소스에서 작동하지 않는지 모르겠습니다.나는 당신이 지적한 대로 $column 및 약속과 관련이 있다고 확신합니다.

이를 방지하기 위해 코드에서 빠른 해결 방법을 수행했습니다.다음과 같이 나만의 선택 필터 템플릿을 작성합니다.

<select id="filterTest" class="form-control" 
    ng-model="tableParams.filter()['test']" 
    ng-options="e.id as e.title for e in externaldata">
</select>

컨트롤러에서 이 외부 데이터를 가져옵니다.

$scope.externaldata = Api.query(); // Your custom api call

완벽하게 작동하지만 id 내 데이터에 있으므로 name 기능.

나는 이 솔루션이 최적이 아니라는 것을 이해합니다.누군가 여기에 이 ​​'해결 방법'보다 더 많은 내용을 써서 우리에게 알려주는지 살펴보겠습니다.심지어 에스비트 가끔 여기 있어요 ;)

이것은 나를 위해 작동합니다 :

html :

<td data-title="'Doc type'" filter="{ 'doc_types': 'select' }" filter-data="docTypes()" sortable="'doc_types'">
    {{task.doc_type}}
</td>
.

angularjs :

$scope.docTypes = function ($scope) 
{
    var def = $q.defer();
    //var docType = [
    //    {'id':'4', 'title':'Whatever 1'},
    //    {'id':'9', 'title':'Whatever 2'},
    //    {'id':'11', 'title':'Whatever 3'}
    //];

    // Or get data from API.
    // Format should be same as above.
    var docType = $http.get('http://whatever.dev', {
        params: { param1: data1 }
    });

    //Or with Restangular 
    var docType = Restangular.all('/api/doctype').getList();

    def.resolve(docType);
    return def;
};
.

@ andión이 언급 한 바와 같이 "Nofollow"> 사용자 정의 필터 에서 얻을 수 있습니다.

약속을 가진 비동기 데이터 인구를 쉽게 달성하기 쉽습니다 ( 각 앵무새에서 $ Q 서비스), 흥미로운 Andy 기사 약속에 대한 / em>

$ scope.names 메소드를 수정하고 비동기 데이터를 반환하는 $ HTTP 서비스를 추가하고 다음과 같이 지연된 객체를 해결할 수 있습니다.

$scope.names = function(column) {
  var def = $q.defer();

  /* http service is based on $q service */
  $http({
    url: siteurl + "app/application/fetchSomeList",
    method: "POST",

  }).success(function(data) {

    var arr = [],
      names = [];

    angular.forEach(data, function(item) {
      if (inArray(item.name, arr) === -1) {
        arr.push(item.name);
        names.push({
          'id': item.name,
          'title': item.name
        });
      }
    });
    
    /* whenever the data is available it resolves the object*/
    def.resolve(names);

  });

  return def;
};
.

비슷한 문제가 있었지만 필터 값을 가져 오기 위해 추가 Ajax 호출을 만들고 싶지는 않습니다.

OP의 코드의 문제는 $ scope.data가 채워지기 전에 필터 데이터 기능이 실행된다는 것입니다.이 문제를 해결하려면 Angular $ 워치를 사용하여 $ scope.data의 변경 사항을 수신합니다.$ scope.data가 유효 한 경우 필터 데이터가 올바르게 채워집니다.

        $scope.names2 = function () {
        var def = $q.defer(),
             arr = [],
                names = [];
        $scope.data = "";
        $scope.$watch('data', function () {


            angular.forEach($scope.data, function (item) {
                if (inArray(item.name, arr) === -1) {
                    arr.push(item.name);
                    names.push({
                        'id': item.name,
                        'title': item.name
                    });
                }
            });

        });
        def.resolve(names);
        return def;
    };
.

변경 사항이있는 원래의 플락 : http://plnkr.co/edit/sjxvppqr2ziyasyavbqhqa

또한 $ watch에 대한 질문도 이것을 볼 수 있습니다 : $ scope을 어떻게 사용합니까?시계 및 $ Scope. Angularjs에 $ 적용

Diablo

가 언급 한 $ q.defer ()로 문제를 해결했습니다.

그러나 실제로는 실제로 꽤 간단하고 간단합니다 :

html :

<td ... filter-data="countries">
.

컨트롤러 :

$scope.countries = $q.defer();
$http.get("/getCountries").then(function(resp){
  $scope.countries.resolve(resp.data.data);
})
.

"먼저 NGTable SELECT 필터 템플리트를 무시해야합니다 (이를 수행하는 방법을 모르는 경우, $ TEMPLATECACHE를 사용하는 것이 포함되며 재정의 해야하는 키는 'NG 테이블 / 필터 / 선택이 포함됩니다.html '). "

NG 테이블의 스크립트 아래에있는 무시 스크립트를 추가했으며 모든 것이 잘 작동했습니다 ...

<script id="ng-table/filters/select.html" type="text/ng-template">
 <select ng-options="data.id as data.title for data in {{$column.data}}" ng-table-select-filter-ds="$column" ng-disabled="$filterRow.disabled" ng-model="params.filter()[name]" class="filter filter-select form-control" name="{{name}}"> <option style="display:none" value=""></option> </select>
</script>
.

내가 한 일은 선택 태그를 값으로 넣고 NG-Model이 필터의 값을 반환하게하는 것만으로 만드는 것입니다.

이것은 일반 텍스트를 번역 할 필요가 있으므로 도움이되었습니다.

<td data-title="'Status'| translate" ng-bind = "("cc_assignment_active"== '0') ? ('Inactive' | translate) : ('Active'| translate)" 
                    filter="{ cc_assignment_active: 'select3'}" >

</td>

<script id="ng-table/filters/select3.html" type="text/ng-template">
<select  class="filter filter-select form-control"  ng-model="params.filter()[name]" name="{{name}}">
    <option active value="" translate>---All---</option>
    <option value="1" translate>Active</option>
    <option value="0" translate>Inactive</option>
</select>
.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top