Issue 1:
I'm submitting a ... (check one with "x")

[X ] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

Changing value of enabled <input type="file"> doesn't trigger any validators. Only need to change type to "text" and everything is working as expected.

Expected behavior

Changing value of <input type="file"> should trigger validators.

Minimal reproduction of the problem with instructions

View

<md-card>
<md-card-title>Audio test creator</md-card-title>
<md-card-content>
<form [formGroup]="creationForm" (ngSubmit)="onSubmit(creationForm)">

<select (change)="onChange($event.target.value)" class="custom-select" formControlName="method">
<option value="" selected disabled>Test method</option>
<option *ngFor="let testMethod of testMethods" [value]="testMethod.value">
{{testMethod.display}}
</option>
</select>

<md-input placeholder="Test name" type="text" formControlName="name"></md-input>

<div [formGroup]="abxForm" >
<input type="file" formControlName="soundA" (change)="onInputChange($event.target.value)">
</div>

<button type="submit" [disabled]="!creationForm.valid">Submit</button>
</form>

</md-card-content>
</md-card>

Component class

export class SoundTestCreatorComponent implements OnInit {

readonly ABX_SECTION = "abxForm";

abxForm: FormGroup;
creationForm : FormGroup;

testMethods = [
{value: SoundTestEnum[SoundTestEnum.ABX], display: SoundTestEnum[SoundTestEnum.ABX]},
{value: SoundTestEnum[SoundTestEnum.MUSHRA], display: SoundTestEnum[SoundTestEnum.MUSHRA]}
];

constructor(private fb: FormBuilder) {
this.creationForm = this.fb.group({
"name": ["", Validators.required],
"method": ["", Validators.required],
});

this.abxForm = this.fb.group({
"soundA": ["", CustomValidators.fileInputRequired]
});
}

ngOnInit() { }

onSubmit(creationForm : any) {
console.log('Test creation form submitted');
console.log(creationForm);
}

onChange(selectedMethod : string) {
this.removeFormSections();
if(selectedMethod === SoundTestEnum[SoundTestEnum.ABX]) {
this.addAbxFormSection();
}
if(selectedMethod === SoundTestEnum[SoundTestEnum.MUSHRA]) {
}
console.log(selectedMethod);
}

private addAbxFormSection() {
this.creationForm.addControl(this.ABX_SECTION, this.abxForm);
}

private removeFormSections() {
this.creationForm.removeControl(this.ABX_SECTION);
}

onInputChange(val) {
console.log(val);
console.log(this.abxForm.enabled);
}

CustomValidator to check calls.

function isEmptyInputValue(value: any) {
return value == null || typeof value === 'string' && value.length === 0;
}

export class CustomValidators {
static fileInputRequired(c: FormControl) {
return (isEmptyInputValue(c.value)) ? {
fileInputRequired: {
valid: false
}
} : null;
}
}

Angular version: 2.1

Browser: ALL

Language: [ TypeScript 2.0.2 ]

Node (for AoT issues): node --version = 6.0.0

Issue 2:
I'm submitting a ... (check one with "x")

[x] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

I am submitting this as a bug report but it may turn out to be a general limitation in how Angular apps can be built and bundled. Given that there is a similar issue posted on the SystemJS-Builder issue tracker my use case may not be so unique and of interest to a wider community.

Use Case and Current behavior

Consider an NgModule LazyFeatureModule. The feature implements a workflow with a few View Components that may be used in multiple applications.

It was transpiled against Angular 2.4.6 and bundled with Rollup. The entry file to Rollup is foo-feature/index.js which only exports LazyFeatureModule. From this Rollup generates foo-feature/bundle.js which contains all the dependencies required by LazyFeatureModule - including all (ES2015-imported) Angular dependencies - and which eventually exports LazyFeatureModule again. bundle.js was meant to become a pre-bundled Angular module shipped with an npm-package, such that applications which lazily load the bundle don't need to be rebuilt when updating the feature. They should be fine with running an npm update foo-feature on their side.

The application which aims to incorporate the pre-bundled feature has a routing configuration which lazily loads the feature like so:

{path: 'my-foo-feature', loadChildren: './node_modules/foo-feature/bundle.js#LazyFeatureModule'}

The bundle gets loaded, so the paths are correct, but I get an error stating No NgModule metadata found for LazyFeatureModule.

Rollup builds the feature-bundle without warnings and the export produced by Rollup actually looks quite good. These are the last few lines in bundle.js:

// ...
exports.LazyFeatureModule = (function () {
function LazyFeatureModule() {
}
return LazyFeatureModule;
}());
exports.LazyFeatureModule = __decorate([
NgModule({
imports: [
CommonModule,
RouterModule.forChild(ROUTES)
],
declarations: [
HelloView
]
})
], exports.LazyFeatureModule);

So LazyFeatureModule is actually decorated with NgModule metadata and exported. I could track down the problem and the reason seems to be that when Metadata is resolved, a function

function _isNgModuleMetadata(obj) {
return obj instanceof NgModule;
}

is called and returns false.

Above function is included in both bundles. When the error happens it is called inside of app-bundle but obj is a DecoratorFactory of the lazy-loaded feature bundle. Since the feature bundle has been bundled separately, there's not only one but twoNgModule definitions, one in app-bundle and one in feature-bundle. So we got two bundles with two NgModule class definitions. Therefore I suspect that when above code in app-bundle tests a DecoratorFactory of feature-bundle it will test against a different NgModule constructor function reference and therefore returns false for the feature bundle.

As "fix" for the problem at hand I could suggest that above function replaces a hard instanceof check for a test against a special property which indicates that obj is a valid NgModule (something which TypeScript Reference calls Discriminant Properties). However I wonder if my intended use case is possible at all or whether code duplication may also affect dependency injection (which compares against constructor references).

One of the motivations of shipping pre-bundled features was to enable apps to npm-update the feature without the need for a complete rebuild and to ease the build configuration for applications incorporating the feature.

However, as of today deduplication seems to be a strong requirement when building apps out of multiple chunks (multiple chunks are a logical consequence when aiming for lazy-loading). Now the questions which remain for me:

Do you consider this issue a bug or did Angular never intend to support the given use case?

Do you agree with the analysis given in the issue or may I am wrong? If code duplication is a problem should deduplication be mentioned in guides on bundling Angular apps?

Angular version: 2.4.6

... bundles use JIT compiler at the moment

Please tell us about your environment:

rollup@0.41.4

rollup-plugin-commonjs@7.0.0

rollup configured with

format: "iife" for app-bundle

format: "cjs" for feature-bundle

gulp 3.9.1

Browser: [all]

Language: [TypeScript | ES6 | ES5]