0

I am trying to iterate over array but not able to do so (its an array under array). It gives an error:

TypeError: Cannot read property 'toUpperCase' of undefined ("

I am not using toUpperCase anywhere.

The typescript code is :

ngOnInit() {
      this.data = [
          {
              'name': 'Task 1',
              'to_do': ['ToDo1', 'ToDo2', 'ToDo3']
          },
          {
              'name': 'Task 2',
              'to_do': ['ToDo4', 'ToDo5', 'ToDo6']
          }
      ];

  }

The template code is:

<div class="col-md-12">
        Create New Task: <input type="text" name="task" />

        <ul>
          <li *ngFor="let task of data; let i=index; let todo=task.to_do;">
            <div>
              {{ task.name }}
              {{ todo }}
            </div>
            <div *ngFor="let do of todo">
              <input type="text" name="to_do" value="{{ do }}" />
            </div>
          </li>
        </ul>
      </div>
4
  • where are you calling in your code above (toUpperCase), is the code above complete? Commented Apr 1, 2018 at 7:02
  • This kind of error usually occurs when you call (toUpperCase) to a (null) value Commented Apr 1, 2018 at 7:03
  • I am not using toUpperCase in component or template anywhere Commented Apr 1, 2018 at 7:04
  • Could you provide more of that error stack, we can then see what's really happening. Thanks in advance. Commented Apr 1, 2018 at 7:07

1 Answer 1

3

It's actually a template parsing error caused by let todo=task.to_do;

You can only declare local variables for ngFor's exported values (index, odd, even, ...)

https://angular.io/api/common/NgForOf#local-variables

Try this

    <ul>
      <li *ngFor="let task of data; let i=index; ">
        <div>
          {{ task.name }}
          {{ task.to_do}}
        </div>
        <div *ngFor="let do of task.to_do">
          <input type="text" name="to_do" value="{{ do }}" />
        </div>
      </li>
    </ul>

Note: There is an $implicit value exported by ngFor, which equals to the current item in the loop. However, the following does not work (I think it can only evaluate simple assignments

 <li *ngFor="let task of data; let i=index; let todo=$implicit.to_do;">

However,it will work using the ng-template form of ngFor, with the let-variable syntax (but it's more verbose)

        <ng-template ngFor let-todo=$implicit.to_do let-task [ngForOf]="data" let-i="index" >
  <li>
  <div>
              {{ task.name }}
              {{ todo }}
            </div>
            <div *ngFor="let do of todo">
              <input type="text" name="to_do" value="{{ do }}" />
            </div>
            </li>
  </ng-template>

Here is a stackblitz showing both ways

https://stackblitz.com/edit/angular-cces4g?file=app%2Fapp.component.html

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.