116

So I've created this jqueryui widget. Its creates a div that I can stream errors into. The widget code looks like this:

$.widget('ui.miniErrorLog', {
   logStart: "<ul>",   // these next 4 elements are actually a bunch more complicated.
   logEnd:   "</ul>",
   errStart: "<li>",
   errEnd:   "</li>",
   content:  "",
   refs:     [],

   _create: function() { $(this.element).addClass( "ui-state-error" ).hide(); },

   clear: function() { 
      this.content = ""; 
      for ( var i in this.refs )
         $( this.refs[i] ).removeClass( "ui-state-error" );
      this.refs = [];
      $(this.element).empty().hide(); 
   }, 

   addError: function( msg, ref ) {
      this.content += this.errStart + msg + this.errEnd; 
      if ( ref ) {
         if ( ref instanceof Array )
            this.refs.concat( ref );
         else
            this.refs.push( ref );
         for ( var i in this.refs )
            $( this.refs[i] ).addClass( "ui-state-error" );
      }
      $(this.element).html( this.logStart + this.content + this.logEnd ).show();
   }, 

   hasError: function()
   {
      if ( this.refs.length )
         return true;
      return false;
   },
});

I can add error messages into it, and references to page elements that is will put into an error state. I use it to validate dialogs. In the "addError" method I can pass in a single id, or an array of ids, like this:

$( "#registerDialogError" ).miniErrorLog( 
   'addError', 
   "Your passwords don't match.", 
   [ "#registerDialogPassword1", "#registerDialogPassword2" ] );

But when I pass in an array of id's it doesn't work. The problem is in the following lines (i think):

if ( ref instanceof Array )
   this.refs.concat( ref );
else
   this.refs.push( ref );

Why doesn't that concat work. this.refs and ref are both arrays. So why doesn't the concat work?

Bonus: am I doing anything else dumb in this widget? It's my first one.

Rafael Baptista
  • 10,771
  • 4
  • 37
  • 58
  • [JavaScript: How to join / combine two arrays to concatenate into one array?](https://stackoverflow.com/q/3975170/86967) – Brent Bradburn Jun 13 '18 at 04:18
  • Very similar (for arrays instead of strings): ["concat" does not join JavaScript arrays together? - Stack Overflow](https://stackoverflow.com/questions/12810366/concat-does-not-join-javascript-arrays-together) – user202729 Mar 01 '21 at 00:00

6 Answers6

322

The concat method doesn't change the original array, you need to reassign it.

if ( ref instanceof Array )
   this.refs = this.refs.concat( ref );
else
   this.refs.push( ref );
gen_Eric
  • 214,658
  • 40
  • 293
  • 332
Alcides Queiroz
  • 9,156
  • 3
  • 27
  • 42
  • 6
    That did it. I would have thought that a concat method on an object would append to the object. But I guess that's not how it works. – Rafael Baptista Oct 09 '12 at 15:44
  • 4
    @Rafael: The `push` method does that, you could do `[].push.apply(this.refs, ref)` – Bergi Oct 09 '12 at 15:48
87

Here is the reason why:

Definition and Usage

The concat() method is used to join two or more arrays.

This method does not change the existing arrays, but returns a new array, containing the values of the joined arrays.

You need to assign the result of the concatenation back in the array that you have.

Konstantin Dinev
  • 32,797
  • 13
  • 71
  • 95
20

To expand on Konstantin Dinev:

.concat() doesn't add to current object, so this will not work:

foo.bar.concat(otherArray);

This will:

foo.bar = foo.bar.concat(otherArray);
mewc
  • 956
  • 11
  • 21
14

you have to re-assign value using = to array , that you want to get concated value

let array1=[1,2,3,4];
let array2=[5,6,7,8];

array1.concat(array2);
console.log('NOT WORK :  array1.concat(array2); =>',array1);

array1= array1.concat(array2);
console.log('WORKING :  array1 = array1.concat(array2); =>',array1);
Saurabh Mistry
  • 11,077
  • 4
  • 41
  • 64
2
dataArray = dataArray.concat(array2)
double-beep
  • 4,567
  • 13
  • 30
  • 40
PRATHYUSH P
  • 177
  • 1
  • 5
0

Just a note, if you really want to have a mutable array when using the concat function (by mutable I mean that it does not create a new array but mutate the existing one) you can reassign the concat function for that array instance. There is what I did when I needed this.

let myArray = [];

myArray.concat= function(  toAdd){
     if(Array.isArray(toAdd)){
        for(let node of toAdd)
             this.push(node);
      }else
        this.push(toAdd);
}
Andrew S
  • 2,555
  • 3
  • 29
  • 45