Angular prod build error in Cannot assign to a reference or variable
It happened that most exceptions from the AST parser are a headache. Just because they don't carry anything useful, except for just a message:
ERROR in Cannot assign to a reference or variable!
Oh really?
For example, the linker (ViewBuilder
) always writes the place where it cannot build template expressions.
Googling is probably one of the solutions. But the whole circle will be closed on the fact that most answers will offer to check the ngModel
directive usage in template.
The second option is a little bit hardcode. It’s worth getting into the compiler itself and debug. Angular uses node_modules/@angular/compiler/bundles/compiler.umd.js
during compilation.
Let's open this file and try to search the text Cannot assign to a reference or variable!
. We will find the _AstToIrVisitor
class and the visitPropertyWrite
method. There is such a line of code
// Otherwise it's an error.
throw new Error('Cannot assign to a reference or variable!');
The exception is thrown without any information at all
Let's add the console.log(ast)
before the exception, where ast
is the parameter of the visitPropertyWrite
function. The parser will log an instance of the PropertyWrite
class to the console:
PropertyWrite {
span: ParseSpan { start: 0, end: 73 },
receiver: ImplicitReceiver { span: ParseSpan { start: 0, end: 0 } },
name: 'translation',
value: MethodCall {
span: ParseSpan { start: 14, end: 73 },
receiver: ImplicitReceiver { span: [ParseSpan] },
name: 'getTranslationForLanguageFromArticle',
args: [ [PropertyRead], [PropertyRead] ]
}
}
We came to the conclution that we have to understand that relationship between the translation
property and the getTranslationForLanguageFromArticle
method call. As I attempted to clone your example from Bitbucket I looked for the "getTranslationForLanguageFromArticle" usage and found this line in the feed.component.html
:
(change)="translation = getTranslationForLanguageFromArticle($event.value, article)"
This is what the parser cannot understand as translation
is not a class property. It's a local ng-template
variable accessed implicitly in the *ngVar
directive.
I would create some method like changeTranslation
inside the component and do manipulations with article.translations[indexOfCorrectArticleTranslation(article)]
there.
At least you know which way to go :)
If I may add... I got this error, when I named the template-control the same as a binding property of my class. Like this:
<input type="password" class="form-control" name="passwordConfirmation" #passwordConfirmation="ngModel" [(ngModel)]="passwordConfirmation"/>
"passwordConfirmation" is the name of the control in the template AND the name of the property/variable of the component class. This seems to be confusing for the compiler as it tries to bind to the template variable instead of the class property.