FieldedText TypeScript Library
    Preparing search index...

    Write Sequence with Events Example

    This example demonstrates using events to simplify writing files with sequences. Events automatically handle sequence redirects, making the code much cleaner.

    Writes the same pet data as write-sequence example, but uses an event-driven approach that's easier to work with when dealing with complex sequence structures.

    1. onFieldValueWriteReady: Fires for each field before it's written
    2. Automatic Sequence Handling: Events fire in the correct order, accounting for redirects
    3. Declarative Data: Define data in an array, let events map it to fields
    4. onRecordFinished: Fires after each record is written
    // Must manually set each field and track active sequences
    writer.getFieldByName('Type')!.asBigInt = CatType; // Invokes Cat Sequence
    writer.getFieldByName('Name')!.asString = 'Misty';
    writer.getFieldByName('RunningSpeed')!.asFloat = 45.0;
    writer.write();
    // Events fire for each field automatically
    writer.onFieldValueWriteReady = (args) => {
    args.field.value = values[args.recordIndex][args.field.id];
    };

    while (!finished) {
    writer.write(); // Events handle everything
    }
    1. Define data in a 2D array: values[recordIndex][fieldId]
    2. Wire event handler: onFieldValueWriteReady fires for each field
    3. Set field value from the data array using field ID as index
    4. Writer handles redirects: When you set a redirect field value, the writer:
      • Detects the redirect condition
      • Invokes the appropriate sequence
      • Fires subsequent events for the new sequence's fields
    5. No manual tracking needed: You don't need to know which sequence is active

    For a Dog record with training:

    1. onFieldValueWriteReady(Type) → Set Type=2 → Dog Sequence invoked
    2. onFieldValueWriteReady(Name) → Set Name
    3. onFieldValueWriteReady(WalkDistance) → Set WalkDistance
    4. onFieldValueWriteReady(RunningSpeed) → Set RunningSpeed
    5. onFieldValueWriteReady(Training) → Set Training=true → Training Sequence invoked
    6. onFieldValueWriteReady(Trainer) → Set Trainer
    7. onFieldValueWriteReady(SessionCost) → Set SessionCost
    8. onRecordFinished → Record complete
    
    npx tsx examples/write-sequence-events/index.ts
    
    Writing pets with sequences using events:
    
    1,Misty,45
    1,Oscar,35
    2,Buddy,0.5,35,false
    2,Charlie,2,48,true,John,32
    2,Max,0.5,30,false
    3,Bubbles,Orange,Wen
    3,Flash,Yellow,Crucian
    
    Successfully wrote 7 records using event-driven approach
    
    Advantages of using events:
    - No need to manually track which sequences are active
    - onFieldValueWriteReady fires for each field in correct order
    - Automatically handles sequence redirects
    - Simpler code when working with complex sequence structures
    

    Use events when:

    • Working with complex sequence structures
    • Data is in arrays or database results
    • You want cleaner, more maintainable code
    • Multiple sequences with many redirects

    Use manual approach when:

    • Simple data without sequences
    • One-off records with unique values
    • Direct mapping from objects to fields
    // Write Sequence with Events Example
    // Demonstrates using events to simplify writing files with sequences
    // Events automatically handle sequence redirects, making code cleaner

    import {
    FtField,
    FtFieldValueReadyEventArgs,
    FtRecordFinishedEventArgs,
    FtStringWriter,
    FtWriter,
    FtXmlMetaSerialization,
    } from "@pbkware/fielded-text-web";

    // Define Type values
    const CatType = BigInt(1);
    const DogType = BigInt(2);
    const GoldFishType = BigInt(3);

    // Data to write: [recordIndex][fieldId] = value
    // null values indicate fields not used for that record
    const values: FtField.NullableValue[][] = [
    // TypeFieldId, NameFieldId, RunningSpeedFieldId, WalkDistanceFieldId, TrainingFieldId, TrainerFieldId, SessionCostFieldId, ColorFieldId, ChineseClassificationFieldId
    [CatType, "Misty", 45.0, null, null, null, null, null, null],
    [CatType, "Oscar", 35.0, null, null, null, null, null, null],
    [DogType, "Buddy", 35.0, 0.5, false, null, null, null, null],
    [DogType, "Charlie", 48.0, 2.0, true, "John", 32.0, null, null],
    [DogType, "Max", 30.0, 0.5, false, null, null, null, null],
    [GoldFishType, "Bubbles", null, null, null, null, null, "Orange", "Wen"],
    [GoldFishType, "Flash", null, null, null, null, null, "Yellow", "Crucian"],
    ];

    // Load metadata from XML string
    const metaXml = `<?xml version="1.0" encoding="utf-8"?>
    <FieldedText>
    <Field DataType="Integer" Name="Type" />
    <Field Id="1" Name="Name" />
    <Field DataType="Float" Id="2" Name="RunningSpeed" />
    <Field DataType="Float" Id="3" Name="WalkDistance" />
    <Field DataType="Boolean" Id="4" Name="Training" />
    <Field Id="5" Name="Trainer" />
    <Field DataType="Decimal" Id="6" Name="SessionCost" />
    <Field Id="7" Name="Color" />
    <Field Id="8" Name="ChineseClassification" />
    <Sequence Name="Root" Root="True">
    <Item FieldIndex="0">
    <Redirect SequenceName="Cat" InvokationDelay="AfterSequence" Value="1" />
    <Redirect SequenceName="Dog" InvokationDelay="AfterSequence" Value="2" />
    <Redirect SequenceName="GoldFish" InvokationDelay="AfterSequence" Value="3" />
    </Item>
    <Item FieldIndex="1" />
    </Sequence>
    <Sequence Name="Cat">
    <Item FieldIndex="2" />
    </Sequence>
    <Sequence Name="Dog">
    <Item FieldIndex="3" />
    <Item FieldIndex="2" />
    <Item FieldIndex="4">
    <Redirect SequenceName="Training" InvokationDelay="AfterField" Value="True" />
    </Item>
    </Sequence>
    <Sequence Name="GoldFish">
    <Item FieldIndex="7" />
    <Item FieldIndex="8" />
    </Sequence>
    <Sequence Name="Training">
    <Item FieldIndex="5" />
    <Item FieldIndex="6" />
    </Sequence>
    </FieldedText>`;

    const meta = FtXmlMetaSerialization.deserialize(metaXml);

    // Track when to stop writing
    let finished = false;

    // Event handler for field value ready
    function handleFieldValueWriteReady(args: FtFieldValueReadyEventArgs): void {
    const field = args.field;
    const recordIndex = args.recordIndex;

    const id = field.id;
    if (id === undefined) {
    throw new Error("Field id is undefined");
    } else {
    // Simply set the field value from our data array
    // The event fires for each field in the correct order,
    // automatically taking sequence redirects into account
    field.value = values[recordIndex][id];
    }
    }

    // Event handler for record finished
    function handleRecordFinished(args: FtRecordFinishedEventArgs): void {
    if (args.recordIndex >= values.length - 1) {
    finished = true;
    }
    }

    // Create writer
    const stringWriter = new FtStringWriter();
    const writer = new FtWriter(meta, stringWriter);

    // Wire up event handlers
    writer.onFieldValueWriteReady = (args) => handleFieldValueWriteReady(args); // closure
    writer.onRecordFinished = handleRecordFinished; // function

    console.log("Writing pets with sequences using events:\n");

    // Write records until finished
    // The events handle all the complexity of sequence redirects
    while (!finished) {
    writer.write();
    }

    console.log(stringWriter.toString());
    console.log("\nSuccessfully wrote 7 records using event-driven approach");
    console.log("\nAdvantages of using events:");
    console.log("- No need to manually track which sequences are active");
    console.log("- onFieldValueWriteReady fires for each field in correct order");
    console.log("- Automatically handles sequence redirects");
    console.log("- Simpler code when working with complex sequence structures");