I'm trying to pass html to a viewchild so it can add it to it's own components html. Until now I haven't found an answer how to solve this.
I'm completely new to Angular, so most of the answers I've read on alot of topics I don't quite understand which makes it pretty hard.
The parent is using NgbModal (#ng-bootstrap/ng-bootstrap) to open a bootstrap modal. Since I don't want to keep repeating the same code for the modal itself all trough the project, I want to use a component for it. The modal component (viewchild) is working, except that I can't manage to pass html to the modal component so it can use the html to fill in the modal-body.
Triggering the modal like:
this.modalService.open(content, options).result;
Is there some way to use the inner html for example like:
<app-modal #modal>
<img src="test.png" alt="test" />
</app-modal>
So the image will be the content of the bootstrap modal.
I managed to finally fix it by wrapping the included component into ng-template.
Parent component's html including the module/viewChild:
<ng-template #imageFileModalContent let-c="close" let-d="dismiss">
<app-modal>
<img [src]="msgFile" />
</app-modal>
</ng-template>
Modal's html (viewChild):
<div class="modal-body form-group">
<ng-content></ng-content>
</div>
Read : Content Projection
you can make use of ng-containt : Working Demo
app-modal.component.html (selector will be app-modal)
<div class="dynamiccont">
<ng-content></ng-content>
</div>
when you use this component like this
<app-modal #modal>
<img src="test.png" alt="test" />
</app-modal>
this will work for you, key part is to make use of ng-content which helps you to include content.
Related
I was learning the ng-content. Why need to use it when we can easily write like this
with ng-content
menu.component.html
<div>
<app-message> <h1>Laptop</h1></app-message>
</div>
message.component.html
<div>
<ng-content></ng-content>
<p>something text to be display</p>
<button > Submit</button>
</div>
without ng-content
menu.component.html
<div>
<h1>Laptop</h1>
<app-message> </app-message>
</div>
message.component.html
<div>
<p>something text to be display</p>
<button > Submit</button>
</div>
Using <ng-content> allows you to create flexible reusable components.
For example, a custom app-modal component:
<div class="modal">
<div class="modal-title">
{{title}}
</div>
<div class="modal-body">
<ng-content></ng-content>
</div>
</div>
This is very powerful, and only the start of what you can achieve with <ng-content>
A core prinpiple of software engineering is code reuse (DRY). With this we can bundle all of the logic relating to a component into one component, and inject the content into it.
This is like asking the question
Why not just declare your CSS styles inline instead of in CSS classes?
It is possible, but unmaintainable, and we have evolved beyond that.
Your example is fairly trivial, but it is still useful if you wanted to change style or behaviour based on some injected logic.
There exist some situations when is necessary, maybe no in simple cases but when the app grows up and you have to insert a custom component inside another is very usefully
As you can see from your own example, without using ng-content, the parent component suddenly is partially responsible for the child's layout. It'll get messy real quick, the quicker the more complex the layout gets.
It's useful for displaying components inside of other components, so the components can be reusable. For example, if you want to display some text on a few pages, you call the component with the text inside of the other components that you want the text to be displayed on. It could also be useful for showing different information but styled in the same format. E.g.
if your ng-content already has the information this is an example of how it would be used:
menu.component.html
<ng-content></ng-content>
message.component.html
<ng-content></ng-content>
This is good because you can copy and paste the exact component into another one without having to rewrite the code
If your ng-content is looking for a data source for information to pass into it
<ng-content [data]='data'></ng-content>
This is good because you can recreate the component inside of another component but with different data inside of it.
If you've ever used react, you pass data into it in a similar way here as you would with react props, but instead of props in angular, it will be an #input field. Here is some example code
test.component.html
<ng-content [data]='THIS IS THE DATA'></ng-content>
This is the actual component, as you can see, it is looking for a data source
ng-content.component.html
<p>The data we are looking for is {{data}} </p>
ng-content.component.ts - this says that when the component is called, it is looking for an input called 'data' and the type has to be a string
#Input() data: string;
We would then see the test.component.html displayed like this:
The data we are looking for is THIS IS THE DATA
I have a component called tab which has <ng-content select="[tabItem]"></ng-content>
Sometimes tabItem is inside other child components. My problem is Angular selects the content from direct children, not inner children (app-my-tab), is there any way to do it?
app.component.html
<app-tabs>
<div tabItem>
Tab 1
</div>
<div tabItem>
Tab 2
</div>
<app-my-tab></app-my-tab>
</app-tabs>
my-tab.component.html
<div tabItem>
My Tab
</div>
<div>
Other content
</div>
See this stackblitz
There is no solution for deep selection.
I thing it is logical, because:
understand and real code easily
easy to debug.
If you want really do that use *ngIf in app-my-tab.
To use *ngIF:
All element in app-tabs must have tabItem attribute
send your condition to show/hide some other element in to app-my-tab component. and app-my-tab receive it as #Input() property
in app-my-tab html use *ngIf to show or hide some element
Example: https://stackblitz.com/edit/deep-ng-content-2gyttv?file=src/app/app.component.html
I have an imported css template written on bootstrap, and want to use it inside Angular app.
Seems like exactly custom html attributes don't react a loading from router.
Application characteristics. This is a SPA, and all of pages are loaded inside Navbar Component, with corresponding router-outlet wrapping.
Problem. Any plugin will render included data only after "mechanical" refreshing page with browser "Reload this page" button. But if I change a src for image, from plugin custom attribute, for example
data-background="assets/images/slider_1.jpg"
to
img src="assets/images/slider_1.jpg"
, it will be loaded and shown from the first time.
Example of map plugin. Doesnt show nothing.
<div class="maps-container map-widget m-b-25">
<div class="map" data-addresses="[4.4, -4.4]"
data-icon="assets/images/map-marker.png"
data-zoom="16" data-street-view="1">
</div>
</div>
Example of slider plugin. No background image.
<section class="module-cover parallax text-center"
data-background="assets/images/slider_1.jpg"
data-overlay="0.5">
<div class="container">
<div class="row">
<div class="col-lg-12">
<h1>This is title</h1>
</div>
</div>
</section>
Example of grid item for blog. Here, it should follow masonry style, but renders like strict grid.
<section class="module-cover parallax text-center"
data-background="assets/images/slider_1.jpg"
data-overlay="0.5">
You better use [attr.data]="name-of-custom-attr"
This way angular manages the use of custom html attributes correctly.
I have a container component that has 2 other controllers nested in it. I have them set up like so
container -> component1 and container -> component2
My train of thought here was that I could transclude the HTML from my page into my container component.
<container> <component1></component1> <component2></component2></container>
and then in the container HTML <div ng-init="vm.init()" ng-transclude></div>
Problem is, my container isn't running at all, I added a console log to its init function and no code is running. While component1 and component2 run their init's.
Seems to be a large amount of documentation covering older angular versions. Which tell me that they need to be nested like so <div ng-controller="parentController"> <div ng-controller="childController"></div> </div
How do you nest components into each other in 1.5?
Looks like the issue was that I was attempting to put a ng-init and ng-transclude in the same element. My guess is that ng-transclude overrides everything in the element it is on.
so I moved the ng-init to another element and its working fine
<div ng-transclude ng-init="vm.init()"></div>
changed to
<div ng-init="vm.init()"> <section ng-transclude ></section> </div>
I'm fairly new to AngularJS and trying to learn by doing.
There is a function in a directive I'm looking to access from the view. What I have in my HTML file is
<div collapse class="collapsed" ng-click="toggle()" ></div>
What's going on there is the toggle() function should be called on click and change the class to expanded, effectively changing the background image described in the CSS. toggle() is inside the collapse directive.
It doesn't seem to be accessing it though and I'm not sure why. Is there another way to do this or actually access said directive from the view? Could you explain why it's not accessing it?
Could this question possibly help? 15672709, it leads to this fiddle and goes beyond in case you nest your directives like below:
<div ng-controller="MyCtrl">
<div screen>
<div component>
<div widget>
<button ng-click="widgetIt()">Woo Hoo</button>
</div>
</div>
</div>
</div>