I have an iframe inside an angular component, into which I am injecting a component X dynamically using component factory (appending the native element to the iframe's body). The reason I am doing this is because I need media queries to function in the component. Without ViewEncapsulation.ShadowDom the component injected inside the frame will be 'style-less'.
Until now everything is fine and dandy and the feature works exactly as I want. However, during e2e testing I am not able to access any elements inside the shadow-root , I have tried multiple methods like document.querySelector('component-id').shadowRoot.querySelector('element-id')
and even libraries and work arounds that are mentioned here .
Everything results in the same error
StaleElementReferenceError: stale element reference: stale element not found
To summarize,
I realize this answer might not address your particular question, and that I am running the risk of losing rep due to downvotes, but I would like to suggest a change in architecture, based on my comments to the question above.
Since you have full control over the content of the iframe
I would suggest setting up Angular routing in such a way as to allow you to specify a route for the iframe
that would display your simple component, while keeping the rest of the application's routes intact.
So assuming you have your app's routes set up normally, with a top level component (usually app.component
) which hosts the <router-outlet>
tag, I would create a new top level component (let's call it app-plain.component
) which contains only <router-outlet></router-outlet>
in its template, and nothing else. I would set up the app to use this component as the bootstrap component (instead of app.component
), then I would change the route configuration to move all existing routes as children of a new blank path route ( ''
) with the old app.component
as its component.
Finally I would set up a new route with some path (say iframe
) that would use the component you wish to display in the iframe as its component (let's call it iframe.component
).
This would allow you to put an element such as this <iframe src="/iframe"></iframe>
anywhere in your components, and have it display just your iframe.component
.
Assuming your existing route configuration looks like this:
const routes = [
{ path: '', pathMatch: 'full', redirectTo: 'home' },
{ path: 'home', component: HomeComponent },
// ... more routes here
];
I would modify the route configuration as follows:
const newRoutes = [
{ path: 'iframe', component: IframeComponent },
{
path: '', component: AppComponent, children: routes // <-- the old routes
}
];
As mentioned, I would create a new plain top level component called app-plain.component
with just a <router-outlet>
in its template, and set it up as the module's bootstrap component:
@NgModule({
declarations: [...],
imports: [...],
providers: [...],
bootstrap: [AppPlainComponent] // <-- this is the change
})
export class AppModule { }
NOTE: Since the bootstrap component has changed, you have to specify its selector in your index.html
too (instead of app-root
which it is by default)
I've created a github repo with this solution concept.
I could not make a StackBlitz, because the iframe
never finishes loading when I try, here's my failed attempt .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.