2017-09-20 62 views
1

當我點擊轉到頁面它繼續轉到第1頁。我基於現有的功能。對我來說Angular 4是相當新的。我剛從Angular 1開始。角4數據表頁面不起作用。 NGX商店,效果

奇怪的是,頁面組件中的console.log被多次觸發。第一次使用正確的頁碼。但隨後與編號1在一起。我一直在尋找它。但它是完全奇怪的。

在我的網頁我有:

<div class="portlet light"> 
    <div class="portlet-title"> 
    <div class="caption"> 
     <div class="caption-subject bold uppercase" translate>PLAYER_INVENTORY</div> 
    </div> 
    </div> 
    <div class="portlet-body"> 

    <div class="table-responsive"> 
     <storever-datatable [striped]="true" 
          [hover]="true" 
          [data]="inventory$ | async" 
          [count]="count$ | async" 
          [currentPage]="page$ | async" 
          [itemsPerPage]="pageSize$ | async" 
          [orderBy]="orderBy$ | async" 
          (pageChange)="pageChanged($event)" 
          (pageSizeChange)="pageSizeChanged($event)" 
          (orderByChange)="orderByChanged($event)"> 
     <storever-datatable-column [name]="'AUDIO_PLANNINGS_NAME' | translate:lang" 
            [prop]="'media.name'"></storever-datatable-column> 
     <storever-datatable-column [name]="'PLAYER_PLAY_LOGS_FILENAME' | translate:lang" 
            [prop]="'media.fileName'"></storever-datatable-column> 
     <storever-datatable-column [name]="'USERS_LIST_COLUMN_STATUS' | translate:lang" 
            [prop]="'status'"></storever-datatable-column> 

     <storever-datatable-column [name]="'INVENTORY_LAST_MODIFICATION' | translate:lang" 
            [prop]="'lastModified'"> 
      <ng-template let-value="value" storeverDatatableColumnCell> 
      {{ value | moment:lang:dateTimeWithSecondsAndTimezoneFormat:(inventory$ | async)?.timeZone }} 
      </ng-template> 
     </storever-datatable-column> 

     <!-- PREVIEW--> 
     <storever-datatable-column *ngIf="showVideoPreview" 
            [name]="' '" 
            [prop]="'media'"> 
      <ng-template let-value="value" storeverDatatableColumnCell> 
      <i class="fa fa-play fa-lg" aria-hidden="true" (click)="showPreviewDialog(value)"></i> 
      </ng-template> 
     </storever-datatable-column> 

在component.ts

import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core'; 
import {ActivatedRoute, convertToParamMap} from '@angular/router'; 
import {Store} from '@ngrx/store'; 
import {Translation, TranslationService} from 'angular-l10n'; 
import * as _ from 'lodash'; 
import * as moment from 'moment'; 
import {Observable} from 'rxjs/Observable'; 
import {Subscription} from 'rxjs/Subscription'; 

import {DateTimeFormatService, DEFAULT_PAGE_SIZE, replace} from '../../../shared'; 
import * as fromRoot from '../../../shared/reducers'; 
import { 
    ChangeInventoryPageSizeAction, 
    ClearInventoryAction, 
    LoadInventoryAction, 
    OrderInventoryByAction, 
    PageInventoryToAction, 
    SearchInventoryAction, 
    ToggleSearchInventoryAction 
} from '../../actions/inventory'; 
import {VideoPlayerComponent} from '../../components/video-player/video-player.component'; 
import {Inventory} from '../../models/inventory'; 
import {InventoryFilterForm} from '../../models/inventory-filter-form'; 
import {VideoMedia} from '../../models/video-media'; 
import * as fromInventory from '../../reducers'; 

@Component({ selector: 'storever-inventory', templateUrl: './inventory.component.html', styleUrls: ['./inventory.component.scss'] }) 
export class InventoryComponent extends Translation implements OnInit, OnDestroy { 
    @ViewChild('videoPlayer') videoPlayer: VideoPlayerComponent; 
    showFilter$: Observable<boolean>; 
    filter$: Observable<InventoryFilterForm>; 
    page$: Observable<number>; 
    pageSize$: Observable<number>; 
    orderBy$: Observable<string>; 
    inventory$: Observable<Inventory[]>; 
    count$: Observable<number>; 
    showVideoPreview = false; 
    showAudioPreview = false; 
    private sub: Subscription; 
    private dataSub: Subscription; 

    get dateTimeWithSecondsAndTimezoneFormat(): string { return DateTimeFormatService.display.dateTimeWithSecondsAndTimezone; } 

    constructor(private store: Store<fromInventory.AppState>, private activatedRoute: ActivatedRoute, translation: TranslationService) { 
    super(translation); 
    const query$ = this.store.select(fromRoot.selectors.getRouterState).filter(state => !_.isEmpty(state)).map(state => state.queryParams); 
    this.inventory$ = this.store.select(fromInventory.selectors.getInventory); 
    this.showFilter$ = this.store.select(fromInventory.selectors.getInventoryShowFilter); 
    this.filter$ = query$.withLatestFrom(this.inventory$).map(([query, inventory]) => Object.assign({}, { id: _.get<number>(inventory, [0, 'id']) }, name, query)); 

    this.page$ = query$.map(convertToParamMap).map(query => parseInt(query.get('$page') || '1', 10)); 
    this.pageSize$ = query$.map(convertToParamMap).map(query => parseInt(query.get('$length'), 10) || DEFAULT_PAGE_SIZE); 
    this.orderBy$ = query$.map(convertToParamMap).map(query => query.get('$orderBy')); 
    this.count$ = this.store.select(fromInventory.selectors.getInventoryCount); 
    } 

    ngOnInit() { 
    this.store.dispatch(new ClearInventoryAction()); 
    this.sub = this.activatedRoute.queryParams.distinctUntilChanged((x, y) => _.isEqual(x, y)).subscribe(query => { 
     if (_.isEmpty(query)) { 
     this.store.dispatch(replace([], { $page: 1, $length: DEFAULT_PAGE_SIZE, day: moment().format(DateTimeFormatService.input.date) })); 
     } else { 
     this.store.dispatch(new LoadInventoryAction()); 
     } 
    }); 
    this.showVideoPreview = true; 
    /* 
    this.dataSub = this.activatedRoute.data.distinctUntilChanged((x, y) => _.isEqual(x, y)).map(convertToParamMap).subscribe(data => { 
     const type = data.get('type'); 
     this.showVideoPreview = type === 'video'; 
     this.showAudioPreview = type === 'audio'; 
    }); 
    */ 
    } 

    ngOnDestroy() { 
    super.cancelParamSubscriptions(); 
    if (this.sub) { 
     this.sub.unsubscribe(); 
    } 
    } 

    showPreviewDialog(media: VideoMedia): void { this.videoPlayer.open(media); } 

    toggleSearchForm(value: boolean): void { this.store.dispatch(new ToggleSearchInventoryAction(value)); } 

    applyFilter(form: InventoryFilterForm): void { this.store.dispatch(new SearchInventoryAction(form)); } 

    pageChanged(page: number): void { console.log('Page TO action Fired'+page);this.store.dispatch(new PageInventoryToAction(page)); } 

    pageSizeChanged(pageSize: number): void { this.store.dispatch(new ChangeInventoryPageSizeAction(pageSize)); } 

    orderByChanged(orderBy: string): void { this.store.dispatch(new OrderInventoryByAction(orderBy)); } 
} 

在我的影響,我有:

import {Injectable} from '@angular/core'; 
import {Response} from '@angular/http'; 
import {convertToParamMap, Params, Router} from '@angular/router'; 
import {Actions, Effect} from '@ngrx/effects'; 
import {Action, Store} from '@ngrx/store'; 
import {TranslationService} from 'angular-l10n'; 
import * as _ from 'lodash'; 
import * as moment from 'moment'; 

import {ArrayResponse, BaseEffect, DateTimeFormatService, DEFAULT_PAGE_SIZE, error, go, SendBackResult} from '../../shared'; 
import * as fromRoot from '../../shared/reducers'; 
import { 
    ChangeInventoryPageSizeAction, 
    InventoryActionTypes, 
    LoadInventoryFailAction, 
    LoadInventorySuccessAction, 
    OrderInventoryByAction, 
    PageInventoryToAction, 
    SearchInventoryAction 
} from '../actions/inventory'; 
import {Inventory} from '../models/inventory'; 
import {InventoryFilterForm} from '../models/inventory-filter-form'; 
import * as fromPlayers from '../reducers'; 
import {InventoryService} from '../services/inventory-service'; 

@Injectable() 
export class InventoryEffect extends BaseEffect { 
    private routerState$ = this.store.select(fromRoot.selectors.getRouterState).filter(state => !_.isEmpty(state)); 

    @Effect() 
    pageTo$ = this.actions$.ofType<PageInventoryToAction>(InventoryActionTypes.PAGE_TO) 
       .withLatestFrom(this.routerState$.map(state => state.queryParams)) 
       .map(([action, query]) => Object.assign({}, query, { $page: action.payload })) 
       .map(query => go([], query)); 

    @Effect() 
    changePageSize$ = this.actions$.ofType<ChangeInventoryPageSizeAction>(InventoryActionTypes.CHANGE_PAGE_SIZE) 
         .withLatestFrom(this.routerState$.map(state => state.queryParams)) 
         .map(([action, query]) => Object.assign({}, query, { $length: action.payload })) 
         .map(query => go([], query)); 

    @Effect() 
    orderBy$ = this.actions$.ofType<OrderInventoryByAction>(InventoryActionTypes.ORDER_BY) 
       .withLatestFrom(this.routerState$.map(state => state.queryParams)) 
       .map(([action, query]) => Object.assign({}, query, { $orderBy: action.payload })) 
       .map(query => go([], query)); 

    @Effect() 
    search$ = this.actions$.ofType<SearchInventoryAction>(InventoryActionTypes.SEARCH) 
       .withLatestFrom(this.routerState$.map(state => state.queryParams)) 
       .map(([action, query]) => Object.assign({}, query, action.payload, { $page: 1 })) 
       .map(query => go([], query)); 

    @Effect() 
    load$ = this.actions$.ofType(InventoryActionTypes.LOAD) 
      .delayWhen(() => this.routerState$) 
      .debug('Load inventory list action received.') 
      .withLatestFrom(this.routerState$.map(state => state.queryParams)) 
      .map(([action, query]) => this.mapFilterFormToFilter(query)) 
      .withLatestFrom(this.routerState$.map(state => state.params).map(convertToParamMap).map(params => params.get('playerId'))) 
      .switchMap(([filter, playerId]) => this.inventoryService.getList(playerId, filter) 
               .map((payload: SendBackResult<ArrayResponse<Inventory>>) => new LoadInventorySuccessAction(payload.data)) 
               .catch((res: Response) => this.catchResponseError(res))); 

    @Effect() 
    loadFail$ = this.actions$.ofType(InventoryActionTypes.LOAD_FAIL) 
       .debug('A server error occurred while retrieving the inventory.') 
       .map(() => error(this.translation.translate('AUDIO_PLANNINGS_LOAD_ERROR'), this.translation.translate('TOAST_ERROR_TITLE'))); 

    constructor(private actions$: Actions, 
       private store: Store<fromPlayers.AppState>, 
       private translation: TranslationService, 
       private inventoryService: InventoryService, 
       router: Router) { 
    super(router); 
    } 

    protected handleUnhandledError(response: Response): Action { return new LoadInventoryFailAction(response.status); } 

    private mapFilterFormToFilter(params: Params): InventoryFilterForm { 
    const filter: InventoryFilterForm = { 
     name: _.get<string>(params, 'name'), 
     day: moment(_.get<string>(params, 'day'), DateTimeFormatService.input.date, true).toDate(), 
     $page: _.get<number>(params, '$page', 1), 
     $length: _.get<number>(params, '$length', DEFAULT_PAGE_SIZE), 
     $orderBy: _.get<string>(params, '$orderBy') 
    }; 
    return filter; 
    } 
} 

在我的行動,我有:

import {Action} from '@ngrx/store'; 

import {ArrayResponse, type} from '../../shared'; 
import {Inventory} from '../models/inventory'; 
import {InventoryFilterForm} from '../models/inventory-filter-form'; 

export const InventoryActionTypes = { 
    TOGGLE_SEARCH: type('[Inventory] Toggle Search Form'), 
    SEARCH: type('[Inventory] Search'), 
    CHANGE_PAGE_SIZE: type('[Inventory] Change Page Size'), 
    PAGE_TO: type('[Inventory] Page To'), 
    ORDER_BY: type('[Inventory] Order By'), 
    LOAD: type('[Inventory] Load'), 
    LOAD_SUCCESS: type('[Inventory] Load Success'), 
    LOAD_FAIL: type('[Inventory] Load Fail'), 
    CLEAR: type('[Inventory] Clear Data') 
}; 

export class ToggleSearchInventoryAction implements Action { 
    readonly type = InventoryActionTypes.TOGGLE_SEARCH; 
    constructor(public payload?: boolean) {} 
} 

export class SearchInventoryAction implements Action { 
    readonly type = InventoryActionTypes.SEARCH; 
    constructor(public payload?: InventoryFilterForm) {} 
} 

export class ChangeInventoryPageSizeAction implements Action { 
    readonly type = InventoryActionTypes.CHANGE_PAGE_SIZE; 
    constructor(public payload?: number) {} 
} 

export class PageInventoryToAction implements Action { 
    readonly type = InventoryActionTypes.PAGE_TO; 
    constructor(public payload?: number) {} 
} 

export class OrderInventoryByAction implements Action { 
    readonly type = InventoryActionTypes.ORDER_BY; 
    constructor(public payload?: string) {} 
} 

export class LoadInventoryAction implements Action { 
    readonly type = InventoryActionTypes.LOAD; 
    constructor() {} 
} 

export class LoadInventorySuccessAction implements Action { 
    readonly type = InventoryActionTypes.LOAD_SUCCESS; 
    constructor(public payload?: ArrayResponse<Inventory>) {} 
} 

export class LoadInventoryFailAction implements Action { 
    readonly type = InventoryActionTypes.LOAD_FAIL; 
    constructor(public payload?: number) {} 
} 

export class ClearInventoryAction implements Action { 
    readonly type = InventoryActionTypes.CLEAR; 
    constructor() {} 
} 

減速機:

import {Action} from '@ngrx/store'; 
import * as _ from 'lodash'; 

import {DEFAULT_PAGE_SIZE, UserContextActionTypes} from '../../shared'; 
import { 
    ChangeInventoryPageSizeAction, 
    ClearInventoryAction, 
    InventoryActionTypes, 
    LoadInventoryAction, 
    LoadInventoryFailAction, 
    LoadInventorySuccessAction, 
    OrderInventoryByAction, 
    PageInventoryToAction, 
    SearchInventoryAction, 
    ToggleSearchInventoryAction 
} from '../actions/inventory'; 
import {Inventory} from '../models/inventory'; 
import {InventoryFilterForm} from '../models/inventory-filter-form'; 
import {AudioPlaylistsState} from './audio-playlists'; 

export interface InventoryState { 
    showFilter: boolean; 
    array: Inventory[]; 
    count: number; 
} 

const initialState: InventoryState = { 
    showFilter: true, 
    array: [], 
    count: 0, 
}; 

export function inventoryReducer(state = initialState, action: Action): InventoryState { 
    switch (action.type) { 
    case InventoryActionTypes.TOGGLE_SEARCH: 
     return handleToggleSearchAction(state, action); 
    case InventoryActionTypes.CLEAR: 
     return handleClearAction(state); 
    case InventoryActionTypes.LOAD_SUCCESS: 
     return handleLoadSuccessAction(state, action); 
    case InventoryActionTypes.LOAD_FAIL: 
     return handleLoadFailAction(state); 
    case InventoryActionTypes.LOAD: 
     return handleLoadAction(); 
    case UserContextActionTypes.CHANGE_CLIENT: 
     return handleChangeClientAction(); 
    default: 
     return state; 
    } 
} 

function handleToggleSearchAction(state: InventoryState, action: ToggleSearchInventoryAction): InventoryState { 
    const newState: InventoryState = { showFilter: action.payload, array: state.array, count: state.count }; 
    return newState; 
} 

function handleClearAction(state: InventoryState): InventoryState { 
    const newState: InventoryState = { showFilter: state.showFilter, array: [], count: 0 }; 
    return newState; 
} 

function handleLoadSuccessAction(state: InventoryState, action: LoadInventorySuccessAction): InventoryState { 
    const newState: InventoryState = { showFilter: state.showFilter, array: action.payload.array, count: action.payload.count }; 
    return newState; 
} 

function handleLoadFailAction(state: InventoryState): InventoryState { 
    const newState: InventoryState = { showFilter: state.showFilter, array: [], count: 0 }; 
    return newState; 
} 

function handleChangeClientAction(): InventoryState { 
    return { showFilter: true, array: [], count: 0 }; 
} 

function handleLoadAction(): InventoryState { 
    return initialState; 
} 

export const inventorySelectors = { 
    showFilter: (state: InventoryState) => _.get<boolean>(state, 'showFilter', true), 
    array: (state: InventoryState) => _.get<Inventory[]>(state, 'array', []), 
    count: (state: InventoryState) => _.get<number>(state, 'count', 0), 
}; 

這是我的服務

import {Injectable} from '@angular/core'; 
import {Http} from '@angular/http'; 
import {Observable} from 'rxjs/Observable'; 

import {AppSettingsService, ArrayResponse, BaseRestService, SendBackResult, serializeQueryString} from '../../shared'; 
import {Inventory} from '../models/inventory'; 
import {InventoryFilterForm} from '../models/inventory-filter-form'; 

@Injectable() 
export class InventoryService extends BaseRestService { 
    constructor(http: Http, appSettingsService: AppSettingsService) { super(http, appSettingsService); } 

    protected get className(): string { return 'InventoryService'; } 

    protected ge[![enter image description here][1]][1]t isAnonymous(): boolean { return false; } 

    getList(playerId: string, filter: InventoryFilterForm): Observable<SendBackResult<ArrayResponse<Inventory>>> { 
    return this.get(`/logging/devices/${playerId}/inventory/videomedia${serializeQueryString(filter)}`); 
    } 

    getAudioList(playerId: string, filter: InventoryFilterForm): Observable<SendBackResult<ArrayResponse<Inventory>>> { 
    return this.get(`/logging/devices/${playerId}/inventory/audiomedia${serializeQueryString(filter)}`); 
    } 

    getVideoList(playerId: string, filter: InventoryFilterForm): Observable<SendBackResult<ArrayResponse<Inventory>>> { 
    return this.get(`/logging/devices/${playerId}/inventory/videomedia${serializeQueryString(filter)}`); 
    } 
} 
+0

你可以把它放在一個plunkr? – Surreal

+0

問題是這個龐大的項目。我可以嘗試,但是對於Angular的人來說,這很容易被發現? – user3806549

回答

1

我發現erorr。該應用程序要求。頁面加載的原因。

import {Action} from '@ngrx/store'; 
import * as _ from 'lodash'; 

import {DEFAULT_PAGE_SIZE, UserContextActionTypes} from '../../shared'; 
import { 
    ChangeInventoryPageSizeAction, 
    ClearInventoryAction, 
    InventoryActionTypes, 
    LoadInventoryAction, 
    LoadInventoryFailAction, 
    LoadInventorySuccessAction, 
    OrderInventoryByAction, 
    PageInventoryToAction, 
    SearchInventoryAction, 
    ToggleSearchInventoryAction 
} from '../actions/inventory'; 
import {Inventory} from '../models/inventory'; 
import {InventoryFilterForm} from '../models/inventory-filter-form'; 
import {AudioPlaylistsState} from './audio-playlists'; 

export interface InventoryState { 
    showFilter: boolean; 
    array: Inventory[]; 
    count: number; 
} 

const initialState: InventoryState = { 
    showFilter: true, 
    array: [], 
    count: 0, 
}; 

export function inventoryReducer(state = initialState, action: Action): InventoryState { 
    switch (action.type) { 
    case InventoryActionTypes.TOGGLE_SEARCH: 
     return handleToggleSearchAction(state, action); 
    case InventoryActionTypes.CLEAR: 
     return handleClearAction(state); 
    case InventoryActionTypes.LOAD_SUCCESS: 
     return handleLoadSuccessAction(state, action); 
    case InventoryActionTypes.LOAD_FAIL: 
     return handleLoadFailAction(state); 
    /* 
    case InventoryActionTypes.LOAD: 
     return handleLoadAction(); 
    */ 
    case UserContextActionTypes.CHANGE_CLIENT: 
     return handleChangeClientAction(); 
    default: 
     return state; 
    } 
} 

function handleToggleSearchAction(state: InventoryState, action: ToggleSearchInventoryAction): InventoryState { 
    const newState: InventoryState = { showFilter: action.payload, array: state.array, count: state.count }; 
    return newState; 
} 

function handleClearAction(state: InventoryState): InventoryState { 
    const newState: InventoryState = { showFilter: state.showFilter, array: [], count: 0 }; 
    return newState; 
} 

function handleLoadSuccessAction(state: InventoryState, action: LoadInventorySuccessAction): InventoryState { 
    const newState: InventoryState = { showFilter: state.showFilter, array: action.payload.array, count: action.payload.count }; 
    return newState; 
} 

function handleLoadFailAction(state: InventoryState): InventoryState { 
    const newState: InventoryState = { showFilter: state.showFilter, array: [], count: 0 }; 
    return newState; 
} 

function handleChangeClientAction(): InventoryState { 
    return { showFilter: true, array: [], count: 0 }; 
} 
/* 
function handleLoadAction(): InventoryState { 
    return initialState; 
} 
*/ 
export const inventorySelectors = { 
    showFilter: (state: InventoryState) => _.get<boolean>(state, 'showFilter', true), 
    array: (state: InventoryState) => _.get<Inventory[]>(state, 'array', []), 
    count: (state: InventoryState) => _.get<number>(state, 'count', 0), 
}; 

感謝所有的好評。只要始終確保你在網絡中查看呼叫是什麼。

+0

嘿,請將您的答案標記爲問題的答案 – valorkin