Common issues & solutions - aakash14goplani/FullStack GitHub Wiki

  1. Creation of a new project takes forever (longer than 3 minutes)

    • That happens on Windows from time to time => Try running the command line as administrator
    • Or follow these steps
  2. You get an EADDR error (Address already in use)

    • You might already have another ng serve process running - make sure to quit that or use ng serve --port ANOTHERPORT to serve your project on a new port
  3. My changes are not reflected in the browser (App is not compiling)

    • Check if the window running ng serve displays an error. If that's not the case, make sure you're using the latest CLI version and try restarting your CLI
  4. npm WARN npm npm does not support Node.js v9.1.0

    • It turns out that the current installed npm is not compatible with the new node and has a hard time updating. The solution is to uninstall npm: npm uninstall -g npm
  5. Template parse errors: Can't bind to 'colspan' since it isn't a known native property

    • As the message says, the <td> element does not have a colspan property. This is true because colspan is an attribute and colSpan, with a capital S, is the corresponding property. Interpolation and property binding can set only properties, not attributes.
  6. Error: ExpressionChangedAfterItHasBeenCheckedError

    • Usually this is caused by some life cycle callbacks like ngOnInit or ngOnChanges to modify the model (some life cycle callbacks allow modify the model others don't). Nice article: see view child section to rectify this error
    • Don't bind to methods or functions in the view, instead bind to fields and update the fields in event handlers.
    • If you must bind to methods, ensure that they always return the same value instance as long as there wasn't actually a change. Change detection will call these methods a lot.
    /* Error */
    getServerStatus() {
       return this.serverStatus =  Math.random() > 0.5 ? 'Online' : 'Offline'; 
       // Error: ExpressionChangedAfterItHasBeenCheckedError
    }
    
    /* Correct */
    constructor() {
       this.serverStatus = Math.random() > 0.5 ? 'Online' : 'Offline';
    }
    getServerStatus() {
       return this.serverStatus; // one time initialization in constructor to avoid error
    }
    
  7. Adding .json files in .gitignore

    • Don't forget to add package.json, package-lock.json and angular.json to .gitignore file. These are package and system dependent files. Every system may have different versions installed, so making a pull/push request will result into merge conflict.
    • If you have shared these files and want to remove them from git, follow these steps. Run them in Git bash with admin rights.
  8. Sending data via service using pass by value v/s pass by reference

    • Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object.
    • Consider a scenario wherein a service has an array and corresponding getters & setters method
     private ingredientsModelArray: Ingredients[] = [
         new Ingredients('paneer', 4),
         new Ingredients('paratha', 1),
         new Ingredients('mix-veggies', 4),
         new Ingredients('spices', 3)
     ];
    
     ingredientsChanged = new EventEmitter<Ingredients[]>();
    
     getIngredients(): Ingredients[] {
         return this.ingredientsModelArray.slice();
     }
    
     addIngredient(newIngredient: Ingredients) {
         this.ingredientsModelArray.push(newIngredient);
         this.ingredientsChanged.emit(this.ingredientsModelArray.slice());
     }
    
    • If a component makes a call to getIngredients(), it will receive all array contents as the data is passed here by reference.
    • If a component tries to add a particular ingredient to array and then prints contents of array, it won't reflect the newly added element.
    • The reason for this is that when we call getIngredients(), we only get a slice of the ingredients array, so we get a copy. Therefore once we add a new ingredient which we of course don't add to the copy but to the original array, that is not reflected in our components where we only have that copy to work with.
    • Now there are a couple of ways of solving this, for the easiest solution, you could remove slice() and that's not necessarily bad, you would then simply return the original array and if you're sure you don't accidentally edit it somewhere, this might not be wrong.
    • We basically have to inform our component that new data is available. So I will simply add a new event emitter here. This event emitter now can emit our ingredient array and now here whenever we change this array, we simply call this ingredients changed and emit a new event.
    • Modify call to fetch ingredients and add subscribe to catch the data that was emitted by service along with data received initially:
     this.ingredientsModelArray = this.shoppingListService.getIngredients();
     this.shoppingListService.ingredientsChanged.subscribe(
       (ingredient: Ingredients[]) => {
         this.ingredientsModelArray = ingredient;
       }
     );
    
    • FYI, pass by value v/s pass by reference article
  9. Returning Observable within an observable

    • Use combination of take() and exhaustMap(). Refer
  10. While working with service workers you may encounter problems => Error: Expected to find an ngsw-config.json configuration file in the D:\Angular\AngularMultiProjects\projects\service-workers-pwa folder. Either provide one or disable Service Worker in your angular.json configuration file.

  • To be resolved from angular.json file
  • Change to "ngswConfigPath": "./ngsw-config.json"
  • Always run build command within project directory e.g. D:\Angular\AngularMultiProjects\projects\service-workers-pwa>ng build service-workers-pwa --prod