React Redux Toolkit TS - Can't access class methods from my state objects - react-redux

I have set up my redux store and I am able to edit my state objects and get their values. But for some reason I can't call methods on the state objects. It's as if they are stored as javascript objects.
When I call getSequence() the first console.log correctly logs the sequence structure. But the second log call gives me an error
sequence.dump is not a function
Here is my store, including getSequence():
import {configureStore} from '#reduxjs/toolkit'
import sequenceReducer, {selectSequence} from '../feature/sequence-slice'
import midiMapsReducer from '../feature/midimaps-slice'
import {Sequence} from "../player/sequence";
export function getSequence() : Sequence {
const sequence: Sequence = selectSequence(store.getState())
console.log(`getCurrentSequence: ${JSON.stringify(sequence)}`)
console.log(`getCurrentSequence: ${sequence.dump()}`)
return sequence
}
const store = configureStore({
reducer: {
sequence: sequenceReducer,
midiMaps: midiMapsReducer,
}
})
export default store
// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch
I set up my slice state like this:
interface SequenceSliceState {
value: Sequence;
}
const initialState : SequenceSliceState = {
value: new Sequence({})
}
export const sequenceSlice = createSlice({
name: 'sequence',
// type is inferred. now the contained sequence is state.value
initialState,
reducers: {
and here is my Sequence module:
export class SequenceStep {
time: number = 0;
note: number = 64;
velocity: number = 100;
gateLength: number = 0.8;
}
export class MidiSettings {
midiInputDeviceId: string = "";
midiInputDeviceName: string = "";
midiInputChannelNum: number = -1;
midiOutputDeviceId: string = "";
midiOutputDeviceName: string = "";
midiOutputChannelNum: number = 0;
}
export class EnvelopePoint {
time: number = 0;
value: number = 0;
}
export class Envelope {
id: string = "";
controller: string = "";
points: Array<EnvelopePoint> = [];
locked: boolean = true;
mode: string = "loop";
trigger: string = "first";
type: string = "envelope";
// cacheMinValue: number = 0;
// cacheMaxValue: number = 127;
constructor(fake: any) {
this.id = fake.id;
this.controller = fake.controller;
this.points = fake.points;
this.locked = fake.locked;
this.mode = fake.mode;
this.trigger = fake.trigger;
this.type = fake.type;
}
dump() : string {
return "I am an envelope"
}
getValue(time: number) : number {
const numpoints = this.points.length
const length: number = this.points[numpoints - 1].time;
const loop: boolean = true;
const position: number = time % length;
var index = 0
while (index < numpoints && this.points[index].time < position) {
++index
}
if (index == 0) {
return this.points[0].value
} else if (index >= numpoints) {
return this.points[numpoints - 1].value
} else {
const p0: EnvelopePoint = this.points[index - 1];
const p1: EnvelopePoint = this.points[index];
if (p0.time == p1.time) {
return p0.value
} else {
return p0.value + (position - p0.time) / (p1.time - p0.time) * (p1.value - p0.value)
}
}
}
}
export class Sequence {
_id: string = "";
name: string = "";
text: string = "";
user_name: string = "";
user_id: string = "";
steps: Array<SequenceStep> = []
tempo: number = 120.0;
length: number = 8;
numSteps: number = 8;
division: number = 8;
midiSettings: MidiSettings = new MidiSettings();
currentEnvelopeId: string = "";
envelopes: Array<Envelope> = []
constructor(fakeSequence: any) {
this._id = fakeSequence._id;
this.name = fakeSequence.name;
this.text = fakeSequence.text;
this.user_id = fakeSequence.user_id;
this.steps = fakeSequence.steps;
this.tempo = fakeSequence.tempo;
this.length = fakeSequence.length;
this.numSteps = fakeSequence.numSteps;
this.division = fakeSequence.division;
this.midiSettings = fakeSequence.midiSettings;
this.currentEnvelopeId = fakeSequence.currentEnvelopeId;
this.envelopes = new Array<Envelope>();
if (fakeSequence.envelopes) {
for (const fakeEnvelope in fakeSequence.envelopes) {
this.envelopes.push(new Envelope(fakeEnvelope));
}
}
}
dump() : string {
return "I am a Sequence"
}
}
Here is the rest of my sequence slice:
import { createSlice } from '#reduxjs/toolkit'
import { v4 as uuidv4 } from "uuid";
import {Envelope, Sequence} from "../player/sequence"
import {RootState} from "../app/store";
interface SequenceSliceState {
value: Sequence;
}
const initialState : SequenceSliceState = {
value: new Sequence({})
}
export const sequenceSlice = createSlice({
name: 'sequence',
// type is inferred. now the contained sequence is state.value
initialState,
reducers: {
sequenceLoad: (state, payloadAction) => {
console.log(`🍕sequencerSlice.sequenceLoad ${JSON.stringify(payloadAction)}`)
state.value = JSON.parse(JSON.stringify(payloadAction.payload.sequence));
return state;
},
sequenceName: (state, payloadAction) => {
console.log(`🍕sequencerSlice.sequenceName ${JSON.stringify(payloadAction)}`)
state.value.name = payloadAction.payload;
return state
},
numSteps: (state, payloadAction) => {
var sequence: Sequence = state.value
sequence.numSteps = payloadAction.payload;
console.log(`🍕hi from numsteps ${sequence.numSteps} ${sequence.steps.length}`);
if (sequence.numSteps > sequence.steps.length) {
console.log(`🍕extend sequence`);
var newSteps: any = [];
for (var n = sequence.steps.length + 1; n <= sequence.numSteps; n++) {
newSteps = newSteps.concat({ note: 60, velocity: 100, gateLength: 0.9, });
console.log(`added step - now ${newSteps.length} steps`)
}
console.log(`🍕handleNumStepsChange: ${newSteps.length} steps -> ${newSteps}`)
const newStepsArray = sequence.steps.concat(newSteps);
sequence.steps = newStepsArray;
// console.log(`🍕handleNumStepsChange: ${stepsEdits.length} steps -> ${stepsEdits}`)
}
return state
},
midiSettings: (state, payloadAction) => {
console.log(`🍕sequence-slice - payloadAction ${JSON.stringify(payloadAction)}`)
console.log(`🍕sequence-slice - midiSettings ${JSON.stringify(payloadAction.payload)}`)
state.value.midiSettings = payloadAction.payload;
return state
},
division: (state, payloadAction) => {
state.value.division = payloadAction.payload;
return state
},
length: (state, payloadAction) => {
state.value.length = payloadAction.payload;
return state
},
sequenceText: (state, payloadAction) => {
state.value.text = payloadAction.payload;
return state
},
tempo: (state, payloadAction) => {
console.log(`🍕Edit tempo payloadaction ${JSON.stringify(payloadAction)}`)
state.value.tempo = payloadAction.payload
// return { ...state, tempo: parseInt(payloadAction.payload) }
// state.tempo = payloadAction.payload
return state
},
stepControllerValue: (state: any, payloadAction) => {
var sequence: Sequence = state.value
console.log(`🍕Edit stepControllerValue ${JSON.stringify(payloadAction)}`)
const stepNum: number = payloadAction.payload.stepNum
const controllerNum: number = payloadAction.payload.controllerNum
const controllerValue: number = payloadAction.payload.controllerNum
// sequence.steps[stepNum][controllerNum] = controllerValue;
// sequence.steps = steps
return state
},
stepNote: (state, action) => {
const stepnum = action.payload.stepNum
const notenum = action.payload.note
console.log(`🍕sequence-slice.stepNote ${JSON.stringify(action.payload)} ${stepnum} ${notenum}`)
var sequence: Sequence = state.value
// var steps: Array<SequenceStep> = [...sequence.steps];
sequence.steps[stepnum].note = notenum
// sequence.steps = steps;
return state
},
stepGateLength: (state, action) => {
const stepnum = action.payload.stepNum
const gateLength = action.payload.gateLength
// console.log(`🍕sequence-slice.stepNote ${JSON.stringify(action.payload)} ${stepnum} ${notenum}`)
// var steps = [...state.steps];
var sequence: Sequence = state.value
sequence.steps[stepnum].gateLength = gateLength
// state.steps = steps;
return state
},
stepVelocity: (state, action) => {
const stepnum = action.payload.stepNum
const velocity = action.payload.velocity
// console.log(`🍕sequence-slice.stepNote ${JSON.stringify(action.payload)} ${stepnum} ${notenum}`)
var sequence: Sequence = state.value
// var steps = [...state.steps];
sequence.steps[stepnum].velocity = velocity
// state.steps = steps;
return state
},
decrement: state => {
var sequence: Sequence = state.value
sequence.numSteps -= 1;
return state
},
// incrementByAmount: (state, action) => {
// var sequence: Sequence = state.value
// sequence.numSteps += action.payload;
// return state
// },
createEnvelope: (state, action) => {
console.log(`🍕sequenceSlice - createEnvelope: action should be controller ${JSON.stringify(action)}`)
const controller = action.payload.controller
console.log(`🍕sequenceSlice - createEnvelope: controller ${JSON.stringify(controller)}`)
var sequence: Sequence = state.value
var newEnvelopeId = uuidv4()
var newEnvelope = new Envelope({
id: newEnvelopeId,
controller: controller.name,
points: [{ time: 0, value: 0}, ],
locked: true,
mode: "loop",
trigger: "first",
type: "envelope"
})
if (sequence.envelopes == null) {
sequence.envelopes = new Array<Envelope>();
}
sequence.envelopes = [...sequence.envelopes, newEnvelope];
sequence.currentEnvelopeId = newEnvelopeId;
// console.log(`🍕state.envelopes <${state.envelopes}> (added ${newEnvelopeId}`);
return state
},
envelopeValue: (state, action) => {
console.log(`🍕sequenceSlice - envelopeValue: action ${JSON.stringify(action)}`)
const ccValue = action.payload.value
const controller = action.payload.controller
const envelopeId = action.payload.envelopeId
var sequence: Sequence = state.value
var envelope = sequence.envelopes.find((envelope: any) => envelope.id === envelopeId);
if (envelope) {
console.log(`🍕envelope ${envelopeId} ${JSON.stringify(envelope)}`)
const ccid = action.payload.ccid
// const currentValue = envelope.points[0].value
// const currentLsb = currentValue % ((controller.max + 1) / 128)
// const currentMsb = currentValue - currentLsb
// const value = action.payload.value * ((controller.max + 1) / 128)
envelope.points[0] = {time: 0, value: action.payload.value}
}
return state
},
currentEnvelopeId: (state, action) => {
console.log(`🍕sequence-slice: action ${JSON.stringify(action)}`)
var sequence: Sequence = state.value
console.log(`🍕sequence-slice: currentEnvelopeId - was ${sequence.currentEnvelopeId}`);
sequence.currentEnvelopeId = action.payload.envelopeId;
console.log(`🍕sequence-slice: currentEnvelopeId - now ${sequence.currentEnvelopeId}`);
return state
},
addEnvelopePoint(state, action) {
console.log(`addEnvelopePoint: action ${JSON.stringify(action)}`)
const envelopeId = action.payload.envelopeId
var sequence: Sequence = state.value
var envelope = sequence.envelopes.find((envelope: any) => envelope.id === envelopeId);
if (envelope) {
envelope.points.push({time: action.payload.time, value: action.payload.value})
envelope.points = envelope.points.sort((a,b) => { return a.time - b.time })
console.log(`addEnvelopePoint: found envelope. Points are now ${JSON.stringify(envelope.points)}`)
}
return state
},
deleteEnvelopePoint(state, action) {
console.log(`deleteEnvelopePoint: point ${JSON.stringify(action.payload)} ${action.payload.envelopeId}`)
const envelopeId = action.payload.envelopeId
var sequence: Sequence = state.value
var envelope = sequence.envelopes.find((envelope: any) => envelope.id === envelopeId);
if (envelope) {
console.log(`deleteEnvelopePoint: envelope ${JSON.stringify(envelope)} ${envelope.points.length}`)
for (var n = 0; n < envelope.points.length; n++) {
console.log(`envelope.points[n] ${JSON.stringify(envelope.points[n])} == action.payload.point ${JSON.stringify(action.payload.point)}`)
if (envelope.points[n].time == action.payload.point.time && envelope.points[n].value == action.payload.point.value) {
envelope.points.splice(n, 1)
console.log('deleteEnvelopePoint: found it')
console.log(`deleteEnvelopePoint: envelope ${JSON.stringify(envelope)} ${envelope.points.length}`)
break;
}
}
}
return state
},
moveEnvelopePoint(state, action) {
console.log(`moveEnvelopePoint: point ${JSON.stringify(action.payload)} ${action.payload.envelopeId}`)
console.log(`moveEnvelopePoint: point ${JSON.stringify(action)}`)
const envelopeId = action.payload.envelopeId
const pointNum : number = action.payload.pointNum
const time : number = action.payload.time
const value : number = action.payload.value
var sequence: Sequence = state.value
var envelope = sequence.envelopes.find((envelope: any) => envelope.id === envelopeId);
if (envelope) {
console.log(`moveEnvelopePoint: envelope ${JSON.stringify(envelope)} point ${pointNum} -> ${time},${value}`)
envelope.points[pointNum].time = time
envelope.points[pointNum].value = value
}
return state
}
}
})
export const {
sequenceLoad,
sequenceName,
numSteps,
midiSettings,
division,
sequenceText,
length,
tempo,
stepControllerValue,
stepNote,
stepGateLength,
stepVelocity,
decrement,
envelopeValue,
addEnvelopePoint,
deleteEnvelopePoint,
currentEnvelopeId,
moveEnvelopePoint,
} = sequenceSlice.actions
export const selectSequence = (state: RootState) => state.sequence.value
export default sequenceSlice.reducer

The moment you call JSON.parse(JSON.stringify(payloadAction.payload.sequence)), you create a normal JavaScript object that just has the properties of the class instance, but not the functionality.
Generally, you should not be storing things like class instances in a Redux store - classes cannot be serialized (as you just saw here), which causes problems with the devtools and libraries like redux-persist. Also, they tend to modify themselves, which collides with the core tenets of Redux.
Store pure data instead, use reducers to do modifications and selectors to derive further data from it.

Related

Failed import using amCharts5 and Nuxt 3

I am trying to implement amCharts3 in Nuxt 3 and am getting the following error in the console:
"Uncaught SyntaxError: The requested module '/_nuxt/#fs/Users/[...]/ui/client/node_modules/regression/dist/regression.js?v=7015616a' does not provide an export named 'default' (at RegressionSeries.ts:5:8)".
Snapshot of RegressionSeries.ts file
The RegressionSeries.ts is imbedded in the amCharts module...amcharts5>.internal.charts.stock.drawing>RegressionSeries.js. Here the file which is the source of the error:
import { SimpleLineSeries } from "./SimpleLineSeries";
import regression from "regression";
export class RegressionSeries extends SimpleLineSeries {
constructor() {
super(...arguments);
Object.defineProperty(this, "_tag", {
enumerable: true,
configurable: true,
writable: true,
value: "regression"
});
}
_updateSegment(index) {
const diP1 = this._di[index]["p1"];
const diP2 = this._di[index]["p2"];
const series = this.get("series");
if (series && diP1 && diP2) {
const xAxis = series.get("xAxis");
let x1 = this._getXValue(diP1.get("valueX"));
let x2 = this._getXValue(diP2.get("valueX"));
const di1 = xAxis.getSeriesItem(series, xAxis.valueToPosition(x1));
const di2 = xAxis.getSeriesItem(series, xAxis.valueToPosition(x2));
const field = this.get("field") + "Y";
if (di1 && di2) {
const dataItems = series.dataItems;
let startIndex = dataItems.indexOf(di1);
let endIndex = dataItems.indexOf(di2);
let inversed = false;
if (startIndex > endIndex) {
inversed = true;
[startIndex, endIndex] = [endIndex, startIndex];
}
const points = [];
let ii = 0;
for (let i = startIndex; i <= endIndex; i++) {
const dataItem = dataItems[i];
points.push([ii, dataItem.get(field)]);
ii++;
}
const result = regression.linear(points);
const resultPoints = result.points;
const len = resultPoints.length;
if (len > 1) {
const p1 = resultPoints[0];
const p2 = resultPoints[resultPoints.length - 1];
if (p1 && p2) {
let y1 = p1[1];
let y2 = p2[1];
if (inversed) {
[y1, y2] = [y2, y1];
}
this._setContext(diP1, "valueY", y1, true);
this._setContext(diP2, "valueY", y2, true);
this._setContext(diP1, "valueX", x1);
this._setContext(diP2, "valueX", x2);
this._positionBullets(diP1);
this._positionBullets(diP2);
}
}
}
}
}
// need to override so that location would not be set
_setXLocation() {
}
}
Object.defineProperty(RegressionSeries, "className", {
enumerable: true,
configurable: true,
writable: true,
value: "RegressionSeries"
});
Object.defineProperty(RegressionSeries, "classNames", {
enumerable: true,
configurable: true,
writable: true,
value: SimpleLineSeries.classNames.concat([RegressionSeries.className])
});
//# sourceMappingURL=RegressionSeries.js.map
added the amcharts.client.ts plugin like this:
import * as am5 from '#amcharts/amcharts5'
import * as am5xy from '#amcharts/amcharts5/xy'
import * as am5radar from '#amcharts/amcharts5/radar'
import * as am5stock from '#amcharts/amcharts5/stock'
import am5themes_Animated from '#amcharts/amcharts5/themes/Animated'
export default defineNuxtPlugin(() => {
return {
provide: {
am5,
am5xy,
am5radar,
am5stock,
am5themes_Animated,
},
}
})
and other charts have worked, so I am fairly certain that the setup is correct.
For those interested:
I had amCharts5 set set up for transpiling in the NuxtConfig file. Removing it resolved the error.

How to update CSV in each it blocks in Cypress

I want to update CSV file data (Ex: columns data like orderId, date etc...) in each it blocks of spec file. I have written code to update CSV inside Cypress.config.js file and calling cy.task from spec file. But everytime first it block updated CSV is passed to all other it blocks. Please let me know how can I achieve this
Under uploadOrders.cy.js
/// <reference types='Cypress'/>
import { ORDERS } from '../../selector/orders';
import BU from '../../fixtures/BU.json';
import Helper from '../../e2e/utils/Helper';
const helper = new Helper();
let getTodaysDate = helper.getTodaysDate(); // get today's date and store in getTodaysDate variable
let getTomorrowssDate = helper.getTomorrowsDate(); // get tomorrows's date and store in getTomorrowssDate variable
let getYesterdaysDate = helper.getYesterdaysDate(); // get tomorrows's date and store in getTomorrowssDate variable
describe('Upload Orders', () => {
// Before start executing all it blocks
before(() => {
cy.login(); //login code written in cypress commands.js file
cy.get(ORDERS.ORDER_ICON).click();
});
// Before start executing each it block
beforeEach(() => {
cy.writeFile('cypress/fixtures/finalCsvToBeUploaded.csv', ''); // clears the file before each it block executes
});
// First it block
it('Upload orders and check its successful', () => {
let csvData = {
orderId: 'OrderId_' + helper.getCurrentDateAndTimeInMiliseconds(),
orderDate: getTomorrowssDate,
homebaseExecutionDate: getTomorrowssDate,
customerExecutionDate: getTomorrowssDate,
}
cy.readFile('cypress/fixtures/referenceCsvFile.csv')
.then((data) => {
cy.task('csvToJson', data)
.then(finalJsonArray => {
cy.task('updateCsvData', { csvData, finalJsonArray })
.then(finalUpdatedJsonArray => {
cy.log("Update JSON array: " + finalUpdatedJsonArray[0]['Order ID']);
cy.task('finalCsv', finalUpdatedJsonArray);
});
})
})
cy.get(ORDERS.ORDER_UPLOAD).click();
cy.attachCsvFile('finalCsvToBeUploaded.csv');
cy.validateToastMsg('Orders uploaded successfully');
cy.log('Order is uploaded successfully via csv file and orderId is ');
});
// Second it block
it('Upload orders and check validation for past customer execution date', () => {
cy.wait(5000);
let csvData = {
orderId: 'OrderId_' + helper.getCurrentDateAndTimeInMiliseconds(),
orderDate: getTomorrowssDate,
homebaseExecutionDate: getYesterdaysDate,
customerExecutionDate: getYesterdaysDate,
}
cy.readFile('cypress/fixtures/finalCsvToBeUploaded.csv')
.then((data) => {
cy.task('csvToJson', data)
.then(finalJsonArray => {
cy.task('updateCsvData', { csvData, finalJsonArray })
.then(finalUpdatedJsonArray => {
cy.log("Update JSON array: " + finalUpdatedJsonArray);
cy.task('finalCsv', finalUpdatedJsonArray);
});
})
})
cy.get(ORDERS.ORDER_UPLOAD).click();
cy.attachCsvFile('finalCsvToBeUploaded.csv');
cy.validateToastMsg('Orders uploaded successfully');
cy.log('Order is uploaded successfully via csv file and orderId is');
});
// After exection of all it blocks
after(() => {
// clear cookies and localStorage
cy.clearCookies();
cy.clearLocalStorage();
});
});
Under cypress.config.js file
const { defineConfig } = require("cypress");
const converter = require('json-2-csv');
const csv = require('csv-parser');
const fs = require('fs');
const { default: Helper } = require("./cypress/e2e/utils/Helper");
const csvToJson1 = require('convert-csv-to-json');
const helper = require("csvtojson");
module.exports = defineConfig({
chromeWebSecurity: false,
watchFileForChanges: false,
defaultCommandTimeout: 10000,
pageLoadTimeout: 50000,
viewportWidth: 1280,
viewportHeight: 800,
video: false,
screenshotOnRunFailure: true,
"reporter": "mochawesome",
"reporterOptions": {
"charts": true,
"overwrite": false,
"html": false,
"json": true,
"timestamp": 'dd_mm_yy_HH_MM_ss',
"reportDir": "cypress/reports/mochawesome-report"
},
e2e: {
//To invoke test runner to pick files from the below path
specPattern: 'cypress/e2e/**/*.cy.js',
setupNodeEvents(on, config) {
// implement node event listeners here
// return require('./cypress/plugins/index.js')(on, config)
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
require('#cypress/code-coverage/task')(on, config)
//Start full screen
on('before:browser:launch', (browser = {}, launchOptions) => {
console.log(launchOptions.args);
if (browser.family === 'chromium' && browser.name !== 'electron') {
launchOptions.args.push('--start-fullscreen');
}
if (browser.name === 'electron') {
launchOptions.preferences.fullscreen = true;
}
return launchOptions;
});
//Convert CSV to JSON
on('task', {
csvToJson(data) {
var lines = data.split("\n");
var result = [];
var headers = lines[0].split(",");
for (var i = 1; i < (lines.length); i++) {
var obj = {};
var currentline = lines[i].split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);
for (var j = 0; j < headers.length; j++) {
obj[headers[j]] = currentline[j].replace(/["']/g, "");
}
result.push(obj);
}
console.log(result);
return result;
}
})
// Write updated csv data into file
on('task', {
finalCsv(updatedJSON) {
converter.json2csvAsync(updatedJSON).then(updatedCsv => {
fs.writeFileSync('cypress/fixtures/finalCsvToBeUploaded.csv', updatedCsv);
}).catch(err => console.log(err));
return null;
}
});
//For log purpose; prints message in the console
on('task', {
log(message) {
console.log(message);
return null;
},
});
on('task', {
updateCsvData({ csvData, finalJsonArray }) {
let updatedJSON,orderIds = [];
for (let i = 0; i < (finalJsonArray.length); i++) {
if ('orderId' in csvData) {
orderIds[i] = csvData.orderId;
finalJsonArray[i]['Order ID'] = csvData.orderId;
}
else {
// orderIds[i] = 'OrderId_' + helper.getCurrentDateAndTimeInMiliseconds();
orderIds[i] = 'OrderId_' + Date.now();
finalJsonArray[i]['Order ID'] = orderIds[i];
}
if ('orderDate' in csvData) {
finalJsonArray[i]['Order Date'] = csvData.orderDate;
}
if ('homebaseExecutionDate' in csvData) {
finalJsonArray[i]['Homebase Execution Date'] = csvData.homebaseExecutionDate;
}
if ('customerExecutionDate' in csvData) {
finalJsonArray[i]['Customer Execution Date'] = csvData.customerExecutionDate;
}
}
updatedJSON = finalJsonArray;
return updatedJSON;
}
})
on('task', {
updateCsvFile(csvData) {
const finalJsonArray = [];
let updatedJSON, orderIds = [];
//readFile
fs.createReadStream('cypress/fixtures/referenceCsvFile.csv')
.pipe(csv())
.on('data', (data) => finalJsonArray.push(data))
.on('end', () => {
console.log(finalJsonArray); // CSV converted to json object
//Logic to update json objects; for loop to update csv columns in json array
for (let i = 0; i < (finalJsonArray.length); i++) {
if ('orderId' in csvData) {
orderIds[i] = csvData.orderId;
finalJsonArray[i]['Order ID'] = csvData.orderId;
}
else {
orderIds[i] = 'OrderId_' + this.getCurrentDateAndTimeInMiliseconds();
finalJsonArray[i]['Order ID'] = orderIds[i];
}
if ('orderDate' in csvData) {
finalJsonArray[i]['Order Date'] = csvData.orderDate;
}
if ('homebaseExecutionDate' in csvData) {
finalJsonArray[i]['Homebase Execution Date'] = csvData.homebaseExecutionDate;
}
if ('customerExecutionDate' in csvData) {
finalJsonArray[i]['Customer Execution Date'] = csvData.customerExecutionDate;
}
}
updatedJSON = finalJsonArray;
converter.json2csvAsync(updatedJSON).then(csvFile => {
fs.writeFileSync('cypress/fixtures/' + fileName, csvFile)
}).catch(err => console.log(err));
})
return orderIds;
}
})
return config;
}
}
});
In first it block, CSV file is updating but when controller comes to second it block - considering the same csv file which is updated in first it block but I need to update the csv file separately in second it block
Finally got the answer to my question:
csvData is an object where column data are stored
let csvData = {
orderDate: getTodaysDate,
homebaseExecutionDate: getTomorrowsDate,
customerExecutionDate: getTomorrowsDate
};
Common method to upload the file under commands.js.
Cypress.Commands.add('updateCsvFileData', (csvData, referenceFileName, updatedCsvFileName) => {
cy.readFile('cypress/fixtures/' + referenceFileName)
.then((data) => {
cy.wait(100).then(() => {
cy.task('csvToJson', data)
.then((finalJsonArray) => {
cy.wait(100).then(() => {
cy.task('updateCsvData', { csvData, finalJsonArray })
.then((finalUpdatedJsonArray) => {
cy.wait(100).then(() => {
cy.task('finalCsv', { finalUpdatedJsonArray, updatedCsvFileName })
});
})
})
})
})
})
})
node.js methods:
Convert CSV to JSON object
on('task', {
csvToJson(data) {
var lines = data.split("\n");
var result = [];
var headers = lines[0].split(",");
for (var i = 1; i < (lines.length); i++) {
var obj = {};
var currentline = lines[i].split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);
for (var j = 0; j < headers.length; j++) {
obj[headers[j]] = currentline[j].replace(/["']/g, "");
}
result.push(obj);
}
return result;
}
})
Write updated csv data into CSV file
on('task', {
finalCsv({ finalUpdatedJsonArray, updatedCsvFileName }) {
converter.json2csvAsync(finalUpdatedJsonArray).then(updatedCsv => {
fs.writeFile('cypress/fixtures/' + updatedCsvFileName, updatedCsv);
}).catch(err => console.log(err));
return null;
}
});
Update required fields in CSV file
on('task', {
updateCsvData({ csvData, finalJsonArray }) {
let updatedJSON, orderIds = [];
for (let i = 0; i < (finalJsonArray.length); i++) {
if (csvData.hasOwnProperty('orderId')) {
orderIds[i] = csvData.orderId;
finalJsonArray[i]['Order ID'] = csvData.orderId;
}
else {
let orderIdRandomNum = Date.now() + "_" + Math.floor((Math.random() * 9999) + 1);
orderIds[i] = 'OrderId_' + orderIdRandomNum;
orders[i] = orderIds[i];
finalJsonArray[i]['Order ID'] = orderIds[i];
}
if ('orderDate' in csvData) {
finalJsonArray[i]['Order Date'] = csvData.orderDate;
}
if ('homebaseExecutionDate' in csvData) {
finalJsonArray[i]['Homebase Execution Date'] = csvData.homebaseExecutionDate;
}
if ('customerExecutionDate' in csvData) {
finalJsonArray[i]['Customer Execution Date'] = csvData.customerExecutionDate;
}
if ('teamId' in csvData) {
finalJsonArray[i]['Team ID'] = csvData.teamId;
}
}
updatedJSON = finalJsonArray;
return updatedJSON;
}
})

LinkError: WebAssembly.instantiate(): Import #1 module="go" function="runtime.resetMemoryDataView" error: function import requires a callable

As I'm building my Web assembly application I have bumped into issue with a cryptic error:
LinkError: WebAssembly.instantiate(): Import #1 module="go" function="runtime.resetMemoryDataView" error: function import requires a callable
It is compiled with this command:
GOOS=js GOARCH=wasm go build -o main.wasm main.go server.go
This is the body of index.html, there is nothing in
<body class="is-preload">
<script src="wasm_exec.js"></script>
<script>
wasm_filename = "main.wasm";
function message(s){
document.getElementById("message").textContent = s;
}
function load_wasm(){
if (!WebAssembly.instantiateStreaming) { // polyfill
WebAssembly.instantiateStreaming = async (resp, importObject) => {
const source = await (await resp).arrayBuffer();
return await WebAssembly.instantiate(source, importObject);
};
}
const go = new Go();
WebAssembly.instantiateStreaming(fetch(wasm_filename), go.importObject)
.then(results => { go.run(results.instance); })
.catch((err) => {
message("Error Loading WebAssembly - " + err);
console.error(err);
// location.reload(true);
});
}
load_wasm()
</script>
This is main.go:
import (
"fmt"
"strconv"
"syscall/js"
)
func key(this js.Value, arg []js.Value) interface{} {
arg[0].Call("stopPropagation")
arg[0].Call("preventDefault")
return nil
}
func sum(this js.Value, args []js.Value) interface{} {
var rv interface{}
value1 := js.Global().Get("document").Call("getElementById", args[0].String()).Get("value").String()
value2 := js.Global().Get("document").Call("getElementById", args[1].String()).Get("value").String()
int1, _ := strconv.Atoi(value1)
int2, _ := strconv.Atoi(value2)
js.Global().Get("document").Call("getElementById", "result").Set("value", int1+int2)
return rv
}
func register_callbacks() {
js.Global().Set("key", js.FuncOf(key))
js.Global().Set("sum", js.FuncOf(sum))
}
func init() {
register_callbacks()
fmt.Printf("WebAssembly program started\n")
select {}
}
Then we have the server:
package main
import (
"flag"
"fmt"
"net/http"
)
var listen = flag.String("listen", ":8081", "listen address")
var dir = flag.String("dir", ".", "directory to serve")
func main() {
flag.Parse()
fs := http.FileServer(http.Dir("./assets/"))
http.Handle("/", fs)
fmt.Printf("Web server running. Listening on %q", *listen)
err := http.ListenAndServe(*listen, http.FileServer(http.Dir(*dir)))
fmt.Printf("%v\n", err)
}
This is wasm_exec.js:
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
(() => {
if (typeof global !== "undefined") {
// global already exists
} else if (typeof window !== "undefined") {
window.global = window;
} else if (typeof self !== "undefined") {
self.global = self;
} else {
throw new Error("cannot export Go (neither global, window nor self is defined)");
}
// Map web browser API and Node.js API to a single common API (preferring web standards over Node.js API).
const isNodeJS = global.process && global.process.title === "node";
if (isNodeJS) {
global.require = require;
global.fs = require("fs");
const nodeCrypto = require("crypto");
global.crypto = {
getRandomValues(b) {
nodeCrypto.randomFillSync(b);
},
};
global.performance = {
now() {
const [sec, nsec] = process.hrtime();
return sec * 1000 + nsec / 1000000;
},
};
const util = require("util");
global.TextEncoder = util.TextEncoder;
global.TextDecoder = util.TextDecoder;
} else {
let outputBuf = "";
global.fs = {
constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused
writeSync(fd, buf) {
outputBuf += decoder.decode(buf);
const nl = outputBuf.lastIndexOf("\n");
if (nl != -1) {
console.log(outputBuf.substr(0, nl));
outputBuf = outputBuf.substr(nl + 1);
}
return buf.length;
},
write(fd, buf, offset, length, position, callback) {
if (offset !== 0 || length !== buf.length || position !== null) {
throw new Error("not implemented");
}
const n = this.writeSync(fd, buf);
callback(null, n);
},
open(path, flags, mode, callback) {
const err = new Error("not implemented");
err.code = "ENOSYS";
callback(err);
},
read(fd, buffer, offset, length, position, callback) {
const err = new Error("not implemented");
err.code = "ENOSYS";
callback(err);
},
fsync(fd, callback) {
callback(null);
},
};
}
const encoder = new TextEncoder("utf-8");
const decoder = new TextDecoder("utf-8");
global.Go = class {
constructor() {
this.argv = ["js"];
this.env = {};
this.exit = (code) => {
if (code !== 0) {
console.warn("exit code:", code);
}
};
this._exitPromise = new Promise((resolve) => {
this._resolveExitPromise = resolve;
});
this._pendingEvent = null;
this._scheduledTimeouts = new Map();
this._nextCallbackTimeoutID = 1;
const mem = () => {
// The buffer may change when requesting more memory.
return new DataView(this._inst.exports.mem.buffer);
}
const setInt64 = (addr, v) => {
mem().setUint32(addr + 0, v, true);
mem().setUint32(addr + 4, Math.floor(v / 4294967296), true);
}
const getInt64 = (addr) => {
const low = mem().getUint32(addr + 0, true);
const high = mem().getInt32(addr + 4, true);
return low + high * 4294967296;
}
const loadValue = (addr) => {
const f = mem().getFloat64(addr, true);
if (f === 0) {
return undefined;
}
if (!isNaN(f)) {
return f;
}
const id = mem().getUint32(addr, true);
return this._values[id];
}
const storeValue = (addr, v) => {
const nanHead = 0x7FF80000;
if (typeof v === "number") {
if (isNaN(v)) {
mem().setUint32(addr + 4, nanHead, true);
mem().setUint32(addr, 0, true);
return;
}
if (v === 0) {
mem().setUint32(addr + 4, nanHead, true);
mem().setUint32(addr, 1, true);
return;
}
mem().setFloat64(addr, v, true);
return;
}
switch (v) {
case undefined:
mem().setFloat64(addr, 0, true);
return;
case null:
mem().setUint32(addr + 4, nanHead, true);
mem().setUint32(addr, 2, true);
return;
case true:
mem().setUint32(addr + 4, nanHead, true);
mem().setUint32(addr, 3, true);
return;
case false:
mem().setUint32(addr + 4, nanHead, true);
mem().setUint32(addr, 4, true);
return;
}
let ref = this._refs.get(v);
if (ref === undefined) {
ref = this._values.length;
this._values.push(v);
this._refs.set(v, ref);
}
let typeFlag = 0;
switch (typeof v) {
case "string":
typeFlag = 1;
break;
case "symbol":
typeFlag = 2;
break;
case "function":
typeFlag = 3;
break;
}
mem().setUint32(addr + 4, nanHead | typeFlag, true);
mem().setUint32(addr, ref, true);
}
const loadSlice = (addr) => {
const array = getInt64(addr + 0);
const len = getInt64(addr + 8);
return new Uint8Array(this._inst.exports.mem.buffer, array, len);
}
const loadSliceOfValues = (addr) => {
const array = getInt64(addr + 0);
const len = getInt64(addr + 8);
const a = new Array(len);
for (let i = 0; i < len; i++) {
a[i] = loadValue(array + i * 8);
}
return a;
}
const loadString = (addr) => {
const saddr = getInt64(addr + 0);
const len = getInt64(addr + 8);
return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len));
}
const timeOrigin = Date.now() - performance.now();
this.importObject = {
go: {
// Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters)
// may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported
// function. A goroutine can switch to a new stack if the current stack is too small (see morestack function).
// This changes the SP, thus we have to update the SP used by the imported function.
// func wasmExit(code int32)
"runtime.wasmExit": (sp) => {
const code = mem().getInt32(sp + 8, true);
this.exited = true;
delete this._inst;
delete this._values;
delete this._refs;
this.exit(code);
},
// func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
"runtime.wasmWrite": (sp) => {
const fd = getInt64(sp + 8);
const p = getInt64(sp + 16);
const n = mem().getInt32(sp + 24, true);
fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n));
},
// func nanotime() int64
"runtime.nanotime": (sp) => {
setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
},
// func walltime() (sec int64, nsec int32)
"runtime.walltime": (sp) => {
const msec = (new Date).getTime();
setInt64(sp + 8, msec / 1000);
mem().setInt32(sp + 16, (msec % 1000) * 1000000, true);
},
// func scheduleTimeoutEvent(delay int64) int32
"runtime.scheduleTimeoutEvent": (sp) => {
const id = this._nextCallbackTimeoutID;
this._nextCallbackTimeoutID++;
this._scheduledTimeouts.set(id, setTimeout(
() => { this._resume(); },
getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early
));
mem().setInt32(sp + 16, id, true);
},
// func clearTimeoutEvent(id int32)
"runtime.clearTimeoutEvent": (sp) => {
const id = mem().getInt32(sp + 8, true);
clearTimeout(this._scheduledTimeouts.get(id));
this._scheduledTimeouts.delete(id);
},
// func getRandomData(r []byte)
"runtime.getRandomData": (sp) => {
crypto.getRandomValues(loadSlice(sp + 8));
},
// func stringVal(value string) ref
"syscall/js.stringVal": (sp) => {
storeValue(sp + 24, loadString(sp + 8));
},
// func valueGet(v ref, p string) ref
"syscall/js.valueGet": (sp) => {
const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16));
sp = this._inst.exports.getsp(); // see comment above
storeValue(sp + 32, result);
},
// func valueSet(v ref, p string, x ref)
"syscall/js.valueSet": (sp) => {
Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32));
},
// func valueIndex(v ref, i int) ref
"syscall/js.valueIndex": (sp) => {
storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16)));
},
// valueSetIndex(v ref, i int, x ref)
"syscall/js.valueSetIndex": (sp) => {
Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24));
},
// func valueCall(v ref, m string, args []ref) (ref, bool)
"syscall/js.valueCall": (sp) => {
try {
const v = loadValue(sp + 8);
const m = Reflect.get(v, loadString(sp + 16));
const args = loadSliceOfValues(sp + 32);
const result = Reflect.apply(m, v, args);
sp = this._inst.exports.getsp(); // see comment above
storeValue(sp + 56, result);
mem().setUint8(sp + 64, 1);
} catch (err) {
storeValue(sp + 56, err);
mem().setUint8(sp + 64, 0);
}
},
// func valueInvoke(v ref, args []ref) (ref, bool)
"syscall/js.valueInvoke": (sp) => {
try {
const v = loadValue(sp + 8);
const args = loadSliceOfValues(sp + 16);
const result = Reflect.apply(v, undefined, args);
sp = this._inst.exports.getsp(); // see comment above
storeValue(sp + 40, result);
mem().setUint8(sp + 48, 1);
} catch (err) {
storeValue(sp + 40, err);
mem().setUint8(sp + 48, 0);
}
},
// func valueNew(v ref, args []ref) (ref, bool)
"syscall/js.valueNew": (sp) => {
try {
const v = loadValue(sp + 8);
const args = loadSliceOfValues(sp + 16);
const result = Reflect.construct(v, args);
sp = this._inst.exports.getsp(); // see comment above
storeValue(sp + 40, result);
mem().setUint8(sp + 48, 1);
} catch (err) {
storeValue(sp + 40, err);
mem().setUint8(sp + 48, 0);
}
},
// func valueLength(v ref) int
"syscall/js.valueLength": (sp) => {
setInt64(sp + 16, parseInt(loadValue(sp + 8).length));
},
// valuePrepareString(v ref) (ref, int)
"syscall/js.valuePrepareString": (sp) => {
const str = encoder.encode(String(loadValue(sp + 8)));
storeValue(sp + 16, str);
setInt64(sp + 24, str.length);
},
// valueLoadString(v ref, b []byte)
"syscall/js.valueLoadString": (sp) => {
const str = loadValue(sp + 8);
loadSlice(sp + 16).set(str);
},
// func valueInstanceOf(v ref, t ref) bool
"syscall/js.valueInstanceOf": (sp) => {
mem().setUint8(sp + 24, loadValue(sp + 8) instanceof loadValue(sp + 16));
},
"debug": (value) => {
console.log(value);
},
}
};
}
async run(instance) {
this._inst = instance;
this._values = [ // TODO: garbage collection
NaN,
0,
null,
true,
false,
global,
this._inst.exports.mem,
this,
];
this._refs = new Map();
this.exited = false;
const mem = new DataView(this._inst.exports.mem.buffer)
// Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory.
let offset = 4096;
const strPtr = (str) => {
let ptr = offset;
new Uint8Array(mem.buffer, offset, str.length + 1).set(encoder.encode(str + "\0"));
offset += str.length + (8 - (str.length % 8));
return ptr;
};
const argc = this.argv.length;
const argvPtrs = [];
this.argv.forEach((arg) => {
argvPtrs.push(strPtr(arg));
});
const keys = Object.keys(this.env).sort();
argvPtrs.push(keys.length);
keys.forEach((key) => {
argvPtrs.push(strPtr(`${key}=${this.env[key]}`));
});
const argv = offset;
argvPtrs.forEach((ptr) => {
mem.setUint32(offset, ptr, true);
mem.setUint32(offset + 4, 0, true);
offset += 8;
});
this._inst.exports.run(argc, argv);
if (this.exited) {
this._resolveExitPromise();
}
await this._exitPromise;
}
_resume() {
if (this.exited) {
throw new Error("Go program has already exited");
}
this._inst.exports.resume();
if (this.exited) {
this._resolveExitPromise();
}
}
_makeFuncWrapper(id) {
const go = this;
return function () {
const event = { id: id, this: this, args: arguments };
go._pendingEvent = event;
go._resume();
return event.result;
};
}
}
if (isNodeJS) {
if (process.argv.length < 3) {
process.stderr.write("usage: go_js_wasm_exec [wasm binary] [arguments]\n");
process.exit(1);
}
const go = new Go();
go.argv = process.argv.slice(2);
go.env = Object.assign({ TMPDIR: require("os").tmpdir() }, process.env);
go.exit = process.exit;
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {
process.on("exit", (code) => { // Node.js exits if no event handler is pending
if (code === 0 && !go.exited) {
// deadlock, make Go print error and stack traces
go._pendingEvent = { id: 0 };
go._resume();
}
});
return go.run(result.instance);
}).catch((err) => {
throw err;
});
}
})();
runtime.resetMemoryDataView() function is part of wasm_exec.js support script that bridges WebAssembly binary with JavaScript environment. This and similar errors often mean that wasm_exec.js isn't compatible with WebAssembly binary because version of Golang used to compile binary is different (usually newer) than one wasm_exec.js was taken from.
When running or shipping Golang WebAssembly binary always make sure that you are using wasm_exec.js support script from the same version of Golang as was used to compile binary. You can copy it from $(go env GOROOT)/misc/wasm/wasm_exec.js to be sure.
See official Golang WebAssembly wiki for further details.
As blami suggested a simple:
cp $(go env GOROOT)/misc/wasm/wasm_exec.js ./path/to/old/wasm_exec.js
Worked for me.

local storage value gets overwritten

I have initiated 2 localstorage variables within a typescript function. The second variable holding the value overwrites the first variable. How do I fix it?
OnSelectedOppPropStatsChange(TypeId: string, StrSelectedValue: string): void {
this.appService.SetLoadingShow(true);
var url = this.configs.DashboardDemandStatsURL();
var Input = {
"TypeId": TypeId,
"PS_No": this.user.PS_No,
"StrSelectedValue": StrSelectedValue
};
localStorage.setItem(this.strTypeSelected, StrSelectedValue);
localStorage.setItem(this.strTypeIdValue, TypeId);
this.appService.GetDataFromAPIPost(url, Input)
.then(response => {
this.appService.SetLoadingShow(false);
if (response.ResponseCode == this.configs.RetCodeFailure()) {
this.ShowDemandDetails = false;
this.errorMessage = response.ResponseData;
this.appService.ShowMessagePopup(this.configs.MESSAGETYPEERROR(), this.errorMessage);
}
else {
this.OpenDemandStatsDetails = JSON.parse(response.ResponseData.strDemandStatsOpen);
this.TeamFulfilledStatsDetails = JSON.parse(response.ResponseData.strDemandStatsTeam);
this.RPMFulfilledStatsDetails = JSON.parse(response.ResponseData.strDemandStatsRPM);
this.TotalRRCount = this.OpenDemandStatsDetails.length + this.TeamFulfilledStatsDetails.length + this.RPMFulfilledStatsDetails.length;
}
},
error => { this.errorMessage = <string>error; this.appService.SetLoadingShow(false) });
}
OnClickOpenRRNavigate(): void {
let SelectedItem = localStorage.getItem(this.strTypeSelected);
let SelectedType = localStorage.getItem(this.strTypeIdValue);
this.appService.SetLoadingShow(true);
var url = this.configs.DashboardDemandStatsTableURL();
var Input = {
"TypeId": SelectedType,
"PS_No": this.user.PS_No,
"StrSelectedValue": SelectedItem,
"strRRAllocationValue": this.StrOpenValue
};
this.appService.GetDataFromAPIPost(url, Input)
.then(response => {
this.appService.SetLoadingShow(false);
if (response.ResponseCode == this.configs.RetCodeFailure()) {
this.errorMessage = response.ResponseData;
this.appService.ShowMessagePopup(this.configs.MESSAGETYPEERROR(), this.errorMessage);
}
else {
this.DemandTableDetails = JSON.parse(response.ResponseData.strDemandStatsTable);
this.ShowDemandTable = true;
}
},
error => { this.errorMessage = <string>error; this.appService.SetLoadingShow(false) });
}
In the function OnClickOpenRRNavigate() , the SelectedType and SelectedItem holds the same value. How can I fix it?

How to make ajax call on end of each block with infinite scrolling in ag-grid?

I am using ag-grid with angular 4.
I am using infinite scrolling as the rowModelType. But since my data is huge, we want to first call just 100 records in the first ajax call and when the scroll reaches the end, the next ajax call needs to be made with the next 100 records? How can i do this using ag-grid in angular 4.
This is my current code
table-component.ts
export class AssaysTableComponent implements OnInit{
//private rowData;
private gridApi;
private gridColumnApi;
private columnDefs;
private rowModelType;
private paginationPageSize;
private components;
private rowData: any[];
private cacheBlockSize;
private infiniteInitialRowCount;
allTableData : any[];
constructor(private http:HttpClient, private appServices:AppServices) {
this.columnDefs = [
{
headerName: "Date/Time",
field: "createdDate",
headerCheckboxSelection: true,
headerCheckboxSelectionFilteredOnly: true,
checkboxSelection: true,
width: 250,
cellRenderer: "loadingRenderer"
},
{headerName: 'Assay Name', field: 'assayName', width: 200},
{headerName: 'Samples', field: 'sampleCount', width: 100}
];
this.components = {
loadingRenderer: function(params) {
if (params.value !== undefined) {
return params.value;
} else {
return '<img src="../images/loading.gif">';
}
}
};
this.rowModelType = "infinite";
//this.paginationPageSize = 10;
this.cacheBlockSize = 10;
this.infiniteInitialRowCount = 1;
//this.rowData = this.appServices.assayData;
}
ngOnInit(){
}
onGridReady(params) {
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
//const allTableData:string[] = [];
//const apiCount = 0;
//apiCount++;
console.log("assayApiCall>>",this.appServices.assayApiCall);
const assaysObj = new Assays();
assaysObj.sortBy = 'CREATED_DATE';
assaysObj.sortOder = 'desc';
assaysObj.count = "50";
if(this.appServices.assayApiCall>0){
console.log("this.allTableData >> ",this.allTableData);
assaysObj.startEvalulationKey = {
}
}
this.appServices.downloadAssayFiles(assaysObj).subscribe(
(response) => {
if (response.length > 0) {
var dataSource = {
rowCount: null,
getRows: function (params) {
console.log("asking for " + params.startRow + " to " + params.endRow);
setTimeout(function () {
console.log("response>>",response);
if(this.allTableData == undefined){
this.allTableData = response;
}
else{
this.allTableData = this.allTableData.concat(response);
}
var rowsThisPage = response.slice(params.startRow, params.endRow);
var lastRow = -1;
if (response.length <= params.endRow) {
lastRow = response.length;
}
params.successCallback(rowsThisPage, lastRow);
}, 500);
}
}
params.api.setDatasource(dataSource);
this.appServices.setIsAssaysAvailable(true);
this.appServices.assayApiCall +=1;
}
else{
this.appServices.setIsAssaysAvailable(false)
}
}
)
}
}
I will need to call this.appServices.downloadAssayFiles(assaysObj) at the end of 100 rows again to get the next set of 100 rows.
Please suggest a method of doing this.
Edit 1:
private getRowData(startRow: number, endRow: number): Observable<any[]> {
var rowData =[];
const assaysObj = new Assays();
assaysObj.sortBy = 'CREATED_DATE';
assaysObj.sortOder = 'desc';
assaysObj.count = "10";
this.appServices.downloadAssayFiles(assaysObj).subscribe(
(response) => {
if (response.length > 0) {
console.log("response>>",response);
if(this.allTableData == undefined){
this.allTableData = response;
}
else{
rowData = response;
this.allTableData = this.allTableData.concat(response);
}
this.appServices.setIsAssaysAvailable(true);
}
else{
this.appServices.setIsAssaysAvailable(false)
}
console.log("rowdata>>",rowData);
});
return Observable.of(rowData);
}
onGridReady(params: any) {
console.log("onGridReady");
var dataSource = {
getRows: (params: IGetRowsParams) => {
this.info = "Getting datasource rows, start: " + params.startRow + ", end: " + params.endRow;
console.log(this.info);
this.getRowData(params.startRow, params.endRow)
.subscribe(data => params.successCallback(data));
}
};
params.api.setDatasource(dataSource);
}
Result 1 : The table is not loaded with the data. Also for some reason the service call this.appServices.downloadAssayFiles is being made thrice . Is there something wrong with my logic here.
There's an example of doing exactly this on the ag-grid site: https://www.ag-grid.com/javascript-grid-infinite-scrolling/.
How does your code currently act? It looks like you're modeling yours from the ag-grid docs page, but that you're getting all the data at once instead of getting only the chunks that you need.
Here's a stackblitz that I think does what you need. https://stackblitz.com/edit/ag-grid-infinite-scroll-example?file=src/app/app.component.ts
In general you want to make sure you have a service method that can retrieve just the correct chunk of your data. You seem to be setting the correct range of data to the grid in your code, but the issue is that you've already spent the effort of getting all of it.
Here's the relevant code from that stackblitz. getRowData is the service call that returns an observable of the records that the grid asks for. Then in your subscribe method for that observable, you supply that data to the grid.
private getRowData(startRow: number, endRow: number): Observable<any[]> {
// This is acting as a service call that will return just the
// data range that you're asking for. In your case, you'd probably
// call your http-based service which would also return an observable
// of your data.
var rowdata = [];
for (var i = startRow; i <= endRow; i++) {
rowdata.push({ one: "hello", two: "world", three: "Item " + i });
}
return Observable.of(rowdata);
}
onGridReady(params: any) {
console.log("onGridReady");
var datasource = {
getRows: (params: IGetRowsParams) => {
this.getRowData(params.startRow, params.endRow)
.subscribe(data => params.successCallback(data));
}
};
params.api.setDatasource(datasource);
}

Resources