Domanda

TL: DR

Come posso popolare una tavola NG compresi i filtri "Seleziona" utilizzando Ajax / JSON?

plunk che mostra il problema: http://plnkr.co/zn09lv


.

Dettaglio

Sto cercando di arrivare a impugnati con AngualRJS e l'estensione della tabella NG e sebbene possa ottenere alcune belle tabelle con i filtri di lavoro e tali quando sto usando i dati statici definiti nel JavaScript - una volta che posso provare a caricare I dati reali nella tabella ho colpito un ostacolo.

Il corpo principale della tavola NG è popolato correttamente e purché utilizzo solo il filtro del testo che tutto sembra funzionare:

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

funziona bene.

Tuttavia, se aggiorno questo per utilizzare il filtro Seleziona:

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

Entra in un problema di sincronizzazione in quanto la variabile dei nomi viene sempre valutata prima che i dati siano restituiti dal server. (Forse i nomi Varibale vengono valutati prima che la richiesta al server sia inviata.) Ciò significa che ottengo un elenco vuoto per il filtro.

Una volta che i dati ritorna dal server - non riesco a trovare un modo di aggiornare il filtro Select. Ripetere il codice che crea inizialmente l'elenco dei filtri sembra non avere alcun effetto - non sono sicuro di come attivare la tabella NG per ricontrollare i suoi filtri in modo che la variabile aggiornata non venga letta. Non riesco anche a capire un modo per posticipare la valutazione della variabile fino a quando la chiamata ASYNC è completa.

Per il mio JavaScript ho praticamente utilizzato il codice AJAX di esempio dalla pagina GitHub della tabella NG e ha aggiunto su di esso il codice di esempio per il filtro Seleziona.

    $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;
};
.

Ho provato alcuni tentativi di aggiungere su un ulteriore $ Q.Defer () e avvolgendo i dati iniziali vengono seguiti dalla funzione $ Scope.Names - ma la mia comprensione della promessa e del deferente non è abbastanza forte da ottenere qualsiasi cosa funziona.

Ci sono alcune note su GitHub che suggeriscono questo è un bug nel tavolo NG, ma non sono sicuro che sia così o sto facendo qualcosa di stupido.

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

Puntatori su come procedere notevolmente apprezzati

-kaine -

È stato utile?

Soluzione

Ho avuto un problema simile ma leggermente più complesso. Volevo essere in grado di aggiornare la lista dei filtri dinamicamente che sembrava totalmente fattibili poiché dovrebbero comunque in una variabile di $ ambito. Fondamentalmente, mi aspettavo che, se ho generatodicetagcode, potrei impostare $scope.filterOptions = []; e qualsiasi aggiornamento a quell'elenco si rifletterà automaticamente. Mi sbagliavo.

Ma ho trovato una soluzione che penso sia piuttosto buona. Innanzitutto, è necessario scavalcare il modello di filtro Select NGTAble (nel caso in cui non sai come farlo, implica l'utilizzo di filter-data="filterOptions" e il tasto che devi sovrascrivere è $templateCache).

Nel modello normale, troverai qualcosa come questo 'ng-table/filters/select.html' e il problema con quello è che ng-options="data.id as data.title for data in $column.data" è un valore fisso che non cambierà quando aggiorniamo $column.data.

La mia soluzione è passare solo a $ Scope Key come filtro-dati invece di passare l'intero elenco di opzioni. Quindi, invece di $scope.filterOptions, passerò filter-data="filterOptions" e quindi, metti un piccolo cambiamento nel modello come: filter-data="'filterOptions'".

Ovviamente, questa è una modifica significativa su come funziona il filtro Select. Nel mio caso, è stato per un'app molto piccola che aveva solo un tavolo, ma potresti essere preoccupato che un cambiamento come questo spezzerà le altre tue selezioni. Se questo è il caso, potresti voler costruire questa soluzione in un filtro personalizzato invece di sovrascrivere "Seleziona".

Altri suggerimenti

funziona per me:

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;
};
.

Come menzionato da @ antivi è possibile ottenere con filtro personalizzato .

È facile raggiungere la popolazione di dati asincroni con promesse ( il servizio $ q in angolari), interessante Andy Articolo sulle promesse

È possibile modificare il metodo $ Scope.Names e aggiungere $ http servizio che restituisce i dati asincroni e risolve l'oggetto differito come:

$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;
};
.

Ho riscontrato un problema simile ma non volevo effettuare la chiamata Ajax aggiuntiva per ottenere i valori del filtro.

Il problema con il codice dell'OP è che la funzione dei dati del filtro viene eseguita prima di $ scope.Data è popolata.Per aggirare questo ho usato l'orologio angolare per ascoltare i cambiamenti su $ scope.Data.Una volta $ scope.Data è valido I dati del filtro vengono popolati correttamente.

        $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;
    };
.

L'originale sottile biforculato con il cambiamento: http://plnkr.co/edit/sjxvppqr2ziyasyavbqa

Vedi anche questa questione su $ Guarda: Come posso usare $ ambito. $Guarda e $ Scope. $ Applica in AngularJS?

Ho risolto il problema con $ Q.Defer () come indicato da Diablo

Tuttavia, il codice è in realtà piuttosto semplice e semplice:

In HTML:

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

nel controller:

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

.

"Innanzitutto, è necessario scavalcare il modello di filtro Select NGTAble (nel caso in cui non sai come farlo, implica l'utilizzo di $ TemplateCache e il tasto che devi sovrascrivere è" NG-Table / Filtri / Seleziona.HTML '). "

Ho aggiunto lo script eccessivo sotto lo script della tavola NG e tutto ha funzionato bene ...

<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>
.

Cosa ho fatto è basta inserire il tag SELECT con valori e il modello NG restituisce i valori per il filtro.

Questo è stato utile da quando avevo bisogno di tradurre il testo normale.

<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>
.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top