methuselah
methuselah

Reputation: 13206

Value is assigned to object as a string even though it is a strongly typed

I'm seeing something weird in my code. In this instance below, I have a (change) event that grabs the current value that a user has selected in a dropdown menu.

  <div style="padding-right: 0; width: 100%;">
    <label style="width: 100%;">
      <select
        [(ngModel)]="courseContentButtonSelectedEvent"
        class="course-content-sidebar-form-control"
        (change)="setCourseContentButtonEventStep($event)"
      >
        <option
          *ngFor="let courseContentButtonEvent of courseContentButtonEventList"
          [value]="courseContentButtonEvent.id"
          [selected]="courseContentButtonEvent.id == courseContentButtonSelectedEvent"
          >{{ courseContentButtonEvent.value }}</option
        >
      </select>
    </label>
  </div>

It calls the method setCourseContentButtonEventStep.

  setCourseContentButtonEventStep(event: Event): void {
    const courseContentButtonEventType: CourseContentButtonEventType = ((event.target as HTMLInputElement)
      .value as unknown) as CourseContentButtonEventType;
    let courseContent = JSON.parse(JSON.stringify(this.courseContent));
    this.courseContent = CourseContentService.setCourseContentButtonEventStep(
      courseContent,
      courseContentButtonEventType,
      this.selectedCourseContentUid,
      this.selectedCourseElementUid,
      this.courseContentButtonEventIndex
    );
    this.store.dispatch(builderActions.setCourseContent({ courseContent: courseContent }));
  }

Which then calls the method setCourseContentButtonEventStep in the CourseContentService.

  static setCourseContentButtonEventStep(
    courseContent: ICourseContent[],
    courseContentButtonEventType: CourseContentButtonEventType,
    selectedCourseContentUid: string,
    selectedCourseElementUid: string,
    courseContentButtonEventIndex: number
  ): ICourseContent[] {
    for (let i = 0; i < courseContent.length; i++) {
      if (courseContent[i].uid === selectedCourseContentUid) {
        for (let j = 0; j < courseContent[i].button.length; j++) {
          if (courseContent[i].button[j].uid === selectedCourseElementUid) {
            for (let k = 0; k < courseContent[i].button[j].event.length; k++) {
              if (k == courseContentButtonEventIndex) {
                courseContent[i].button[j].event[k].action = courseContentButtonEventType;
              }
            }
          }
        }
      }
    }
    return courseContent;
  }

Now strangely, despite my casting of courseContentButtonEventType, it gets added to my object as a string instead of a number. For example, see the data object below, under button -> event -> action, specifically "action": "4":

[
  {
    "id": 1,
    "uid": "card-HJUI9b9Nre",
    "body": {
      "text": "Testing"
    },
    "type": 0,
    "button": [
      {
        "uid": "button-4WhgDe8mhe",
        "title": "Get Started",
        "event": [
          {
            "id": 1,
            "action": 5,
            "value": "https://en.wikipedia.org/wiki/Educational_technology"
          },
          {
            "id": 2,
            "action": "4"
          }
        ],
        "isEnabled": true
      }
    ],
    "audio": {
      "uid": "audio-NIiH1fCkqd",
      "url": "https://s3.eu-west-2.amazonaws.com/media.example.co.uk/default/testing_startup_ideas.mp3"
    }
  }
]

Upvotes: 0

Views: 43

Answers (1)

MindingData
MindingData

Reputation: 12460

I think you can clean this up simply by using ngValue instead of value.

<select
[(ngModel)]="courseContentButtonSelectedEvent"
class="course-content-sidebar-form-control"
(ngModelChange)="setCourseContentButtonEventStep($event)"
>
    <option
      *ngFor="let courseContentButtonEvent of courseContentButtonEventList"
      [ngValue]="courseContentButtonEvent"
      [selected]="courseContentButtonEvent.id == courseContentButtonSelectedEvent"
      >{{ courseContentButtonEvent.value }}</option
    >
</select>

Notice the use of ngValue instead of value. Value is always a string whereas ngValue can hold an object (Which is basically what you want).

Also notice the difference of using (change) vs (ngModelChange)

setCourseContentButtonEventStep(courseContentButtonEventType: CourseContentButtonEventType): void {
    let courseContent = JSON.parse(JSON.stringify(this.courseContent));
    this.courseContent = CourseContentService.setCourseContentButtonEventStep(
      courseContent,
      courseContentButtonEventType,
      this.selectedCourseContentUid,
      this.selectedCourseElementUid,
      this.courseContentButtonEventIndex
    );
    this.store.dispatch(builderActions.setCourseContent({ courseContent: courseContent }));
}

Then our event can be cleaned up massively.

I'll also note one thing. Your type in your event handler is " CourseContentButtonEventType". Is this expected? Is that the items in your list?

Upvotes: 1

Related Questions