Trying to iterate through an Array

34 views
Skip to first unread message

nicolas duminil

unread,
Aug 21, 2017, 12:56:11 PM8/21/17
to Angular and AngularJS discussion
Hello,

I'm trying to iterate through an Array, as follows:

myArray = new Array<MyStuff>();
...
console.log(myArray);
console.log("*** myArray.length", myArray.length);
for (let m of myArray) {
  console.log(m);
}

Running this code, correctly displays the content of myArray array, there are 7 MyStuff elements. However, there are none lines displayed in the for ... of loop an,d the displayed value of myArray.length is "undefined". 

I even tried:

for (var i=0; i<myArray.length; i++ {
  console.log(myArray[i]);
}

but no luck neither.

Could someone shed some light and explain me what the hell is happening here ?

Many thanks in advance,

Nicolas  

Tito

unread,
Aug 21, 2017, 6:07:30 PM8/21/17
to Angular and AngularJS discussion
what are you populating your array with?
also you are missing a closing ) on that loop
for (var i=0; i<myArray.length; i++) {
  console.log(myArray[i]);

Sander Elias

unread,
Aug 21, 2017, 10:27:18 PM8/21/17
to Angular and AngularJS discussion
Hi Nicolas,

I don't think your 'myArray' is an actual array. I suspect it's a object. check it out by logging the following:

console.log(typeOf myArray, Array.isArray(myArray))

I suspect the answer will be 'object, false'

Regards
Sander

nicolas duminil

unread,
Aug 22, 2017, 3:40:19 AM8/22/17
to Angular and AngularJS discussion
Hi Sander,

Yes, you're right, this is what I got. However, here is my code:

this.bundleService.getBundles().subscribe((bundlesArray: Array<Bundle>) => {
console.log("*** Got bundles:", bundlesArray);
console.log("*** Types:", typeof bundlesArray, Array.isArray(bundlesArray));
for (let bundle of bundlesArray) {
console.log("*** Got bundle", bundle);
this.bundles.push({label: bundle.label, value: {codePk: bundle.codePk, label: bundle.label, isActive: bundle.isActive}});
}
             ...
So, I have an array of objects of type Bundle. The first log statement correctly displays the content of the array, something like:

*** Got bundles: {bundles: Array(7)}.
 The 2nd log statement displays, as a matter of fact, 

*** Types: object false

and the last log statement is never executed as if the array were empty.

What should I conclude from all this ? My array is not an array or the for ... of loop is not meant to be used in this case ?

Many thanks in advance,

Nicolas

Sander Elias

unread,
Aug 22, 2017, 8:41:22 AM8/22/17
to Angular and AngularJS discussion
Hi Nicolas,

You have an object that looks like an array. I'm not enierly sure, but I suspect i fyou do something like this: 
bundles = Array.from(bundles)

You might need to set the length to the proper number before this works.

Regards
Sander

nicolas duminil

unread,
Aug 23, 2017, 3:39:26 AM8/23/17
to Angular and AngularJS discussion
Hi Sander,

There is something very misterious here and I'll try to explain:

I have the following service:

@Injectable()
export class BundleService {
private url = environment.bundleServiceCallUrl;
constructor(private http: HttpClient) {
}

public getBundles(): Observable<Array<Bundle>> {
const params = new HttpParams().set("start", "0");
return this.http.get<Array<Bundle>>(this.url, { params });
}
}

It returns an array of objects of class Bundle. Its consumer looks as follows:

constructor(private bundleService: BundleService) { }
...
public ngOnInit() {
...
this.bundleService.getBundles().subscribe((bundlesArray: Array<Bundle>) => {this.pushBundles(bundlesArray)},
(err: HttpErrorResponse) => {
if (err.error instanceof Error) {
console.log("### Client-side error occured.");
} else {
console.log("### Server-side error occured.");
}
});
............
}

The service is called normally, it replies with the following array of Bundle objects:

  1. 0: {codePk"DynamicBundle"label"DynamicBundle"isActive"1"}
  1. 1:{codePk"IsoLanguage"label"Iso Languages"isActive"1"}
  2. 2:{codePk"Test_Bundle"label"Test_Bundle"isActive"1"}
  3. 3:{codePk"TranscludeBundles"label"Transclude bundles for tests"isActive"1"}
  4. 4:{codePk"TranscludedBundle1"label"Transcluded bundle 1"isActive"1"}
  5. 5:{codePk"TranscludedBundle2"label"Transcluded bundle 2"isActive"1"}
  6. 6:{codePk"TranscludedBundle1a"label"Transcluded bundle 1a"isActive"1"}

  1. This array of bundles is passed to the pushBundles method, as follows:

  2. private pushBundles(bundlesArray: Array<Bundle>) {
  1. for (let bundle of bundlesArray)
  1. this.bundles.push({label: bundle.label, value: {codePk: bundle.codePk, label: bundle.label, isActive: bundle.isActive}});
    }

    1. And here the for ;;; of loop behaves like the input parameter is not an Array as it display "object false" for typeof bundlesArray, Array.isArray(bundlesArray).

    2. In order to get things running I had to replace in the code above:

    3. this.pushBundles(bundlesArray)

    4. by

    5. this.pushBundles(bundlesArray["bundles"])

I don't know what "bundles" is and where does it comes but this way it works. So, it appears that bundlesArray id not an array of Bundle but something like an array having one element which is my array of Bundle. If you have some ideas to shade some light here, I would be very obligated to you.

Many thanks in advance,

Nicolas


Sander Elias

unread,
Aug 23, 2017, 5:17:05 AM8/23/17
to Angular and AngularJS discussion
Hi Nicolas.

Inspect your network tab, and see what the server returns. I suspect it returns something like this:

"{"bundles":[{"codePk":"DynamicBundle","label":"DynamicBundle","isActive":"1"},{"codePk":"IsoLanguage","label":"Iso Languages","isActive":"1"},{"codePk":"Test_Bundle","label":"Test_Bundle","isActive":"1"},{"codePk":"TranscludeBundles","label":"Transclude bundles for tests","isActive":"1"},{"codePk":"TranscludedBundle1","label":"Transcluded bundle 1","isActive":"1"},{"codePk":"TranscludedBundle2","label":"Transcluded bundle 2","isActive":"1"},{"codePk":"TranscludedBundle1a","label":"Transcluded bundle 1a","isActive":"1"}]}"

what translates to:
{
   
"bundles": [
       
{

           
"codePk": "DynamicBundle",
           
"label": "DynamicBundle",
           
"isActive": "1"

       
},
       
{

           
"codePk": "IsoLanguage",
           
"label": "Iso Languages",
           
"isActive": "1"

       
},
       
{

           
"codePk": "Test_Bundle",
           
"label": "Test_Bundle",
           
"isActive": "1"

       
},
       
{

           
"codePk": "TranscludeBundles",
           
"label": "Transclude bundles for tests",
           
"isActive": "1"

       
},
       
{

           
"codePk": "TranscludedBundle1",
           
"label": "Transcluded bundle 1",
           
"isActive": "1"

       
},
       
{

           
"codePk": "TranscludedBundle2",
           
"label": "Transcluded bundle 2",
           
"isActive": "1"

       
},
       
{

           
"codePk": "TranscludedBundle1a",
           
"label": "Transcluded bundle 1a",
           
"isActive": "1"
       
}

   
]
}

when parsed. 
The backend is giving you back something different as you are expecting.

Regards
Sander

nicolas duminil

unread,
Aug 23, 2017, 10:12:05 AM8/23/17
to Angular and AngularJS discussion
Hi Elias,

Thanks again for your help.

The console logs shows the following:

{bundles: Array(11)}
    1. length:11
So, as a matter of fact, there is a "bundles" key having an array of 11 bundles as its value. Looking at the invoked service, I don't understand where this "bundles" value comes from. Here is the endpoint:

  @GET
  @Produces("application/json")
  public I18nBundleList listAll(@QueryParam("start") Integer startPosition, @QueryParam("max") Integer maxResult)
  {
    List<I18nBundle> bundles = ejb.listAllBundles(startPosition, maxResult);
    return new I18nBundleList(bundles);
  }

It returns a list of I18nBundle objects. A Java client calls it like this:

    I18nBundleList bundles = resource.queryParam("start", "0").queryParam("max", "1").type(MediaType.APPLICATION_JSON).get(I18nBundleList.class);
    assertEquals(bundles.getBundles().size(), 1);

It might be that the Java to JSON marshalling process creates an element named "bundles" as the root of the JSON payload. But why "bundles" and where does it take it name ? And as you may see, in Java one is able to completely abstract the details of the marshalling/unmarshalling process, while using Angular HttpClient, one needs to know the name of the root element that has been generated, probably by the JAX-RS stack. It's quite disapointing in my opinion and it's a serious regression compared to JAX-RS.

Any comments ?

Kind regards,

Nicolas

Sander Elias

unread,
Aug 23, 2017, 10:09:44 PM8/23/17
to Angular and AngularJS discussion
Hi Duminil,

I have no idea on your server-side code. I prefer to stay away off java. There is some sort of wrapping going on in there for sure. To know why, you should examine your server side stack, and work yourself through the taxonomy of that.

Regards
Sander 

nicolas duminil

unread,
Aug 24, 2017, 6:08:28 AM8/24/17
to Angular and AngularJS discussion
Hi Sander,

Yes, you were right, I found the problem. Basically, the back-end returns an object of class BundleList which contains a List<Bundle> named bundles. Hence the Java to JSON serializing process creates a ket/value pair having the name "bundles" with the value a List<Bundle>. This explains the behaviour I have reported. Initially, the back-end was returning the List<Bundle> directly and it has been modified lastly, hence my wrong expectations.

Many thanks for having allowed me to find a pertinent explanation.

Kind regards,

Nicolas
Reply all
Reply to author
Forward
0 new messages