Can you remember "Can't bind 'x' since it is not a known property of 'y'"?
Tags: angular, beginners, webdev
Published: 2020-04-07 09:46:47

This is the most upvoted error in Stackoverflow (https://stackoverflow.com/questions/38892771/cant-bind-to-ngmodel-since-it-isnt-a-known-property-of-input)

Angular has a very decent description of what are the reasons behind this error. In this article, we will dig a little bit further to understand and memorize the reasons in a way so we'll not google again (hopefully!).

Before start, let's have a quick look at what the document says

> This error often means that you haven't declared the directive "x" or haven't imported the NgModule to which "x" belongs.
>
> Perhaps you declared "x" in an application sub-module but forgot to export it. The "x" class isn't visible to other modules until you add it to the `exports` list.

So we'll get this error if we don't import the correct module or if we forgot to export some components.

Let's explore the use cases

## 1. Module is not properly imported 

Let's add a module say `ModuleA`  and a component say `ComponentA` alongside `AppModule` Let's make this module empty

```typescript
@NgModule({
    declarations: [ComponentA],
    imports: [],
    providers: [],
    exports: [ComponentA]
})
export class ModuleA { }
```

Now in the `HTML` try to use `ngFor`

```html
<h1 *ngFor="let foo of bar">{{foo}}</h1>
```

In the console, we'll see a warning

```pseudocode
Can't bind to 'ngForOf' since it isn't a known property of 'h1'.
```

The problem is, it doesn't say which component, to find out we need to expand the warning and see `ComponentA_Template` has this issue.

![ngfor error](https://dev-to-uploads.s3.amazonaws.com/i/lv6t54yd53b4n1jfgp47.PNG)

Also, the warning doesn't tell which module is missing, unfortunately, we need to find out this ourselves, in this case, it is required `CommonModule`.

In a similar fashion, this can happen for `ngModel`  which required `FormsModule`. Even it is applicable for our custom component for example if we forgot to import `ModuleA` to `AppModule` then it'll show a similar type of error.

![Error](https://dev-to-uploads.s3.amazonaws.com/i/19ki2ozwtqz64ob3yqfn.PNG)

**Important to remember, sometimes you'll see this error to browser but most of the time this error is shown in the build**

## 2. Wrong property binding in `HTML` template

We know in general `HTML` is case-insensitive, so if we bind a property wrongly it doesn't show any error for example 

if you write `<td colSpan="2"> `  instead `<td colspan="2">` it'll render correctly but if we try to write something 

`<td colspan="{{1+1}}">` instead `<td colSpan="{{1+1}}">`  

It'll show error

```pseudocode
Template parse errors:
  Can't bind to 'colspan' since it isn't a known native property
```

**Important to remember in Angular most of the property binding is `camelCase` like `ngModel`, `ngClass` and so on**

## 3. Wrong Input/Output declaration

We know this is a very powerful communication medium but sometimes it can be troublesome. So when we are in this situation we need to look the annotation syntax `@` or make sure it is present in the `input/output` array. 

If we declare `Input() public foo: string;` instead `@Input() public foo: string;` but this is hard to reproduce!

So how it can be missing from `input/output` array

```typescript
@Component({
  selector: 'component-a',
  templateUrl: './component-a.html',
  styleUrls: [],
  inputs: ['fooo'] // it can be misspell since it is string
})
```

In the template

```html
<component-a foo="bar"></component-a> 
```

Then we end up with an unpleasant error

```pseudocode
Uncaught Error: Template parse errors:
Can't bind to 'item' since it isn't a known property of 'app-item-detail'
```

**Important to remember, It is a best practice to use annotated `@Input()/@Output()` declaration and avoid alias naming** 

## Rule of thumb

1. If the element is Angular `directive` then check `CommonModule` is in place
2. If the element is `Web Component` then check `CUSTOM_ELEMENTS_SCHEMA` is added to `@NgModule.schemas`
3. If the element is added by you then make sure the respective module is imported and the component is in the export list.
4. If we're using `@Input()/@Output()` follow the best practices, ie. always use the annotated declaration. 

I hope you understand the reasons for this error and you'll avoid the trap. If you have any question please let me know in the comments. Happy coding