At the moment it is not possible to use more then one component in a template. For example:
<div class='wrapper'>
<LeftColumn>
<RightColumn>
<p>text here</p>
</div>
Ractive displays only the first one. The situation is the same if I want to use same component tag twice. It's even more strange when I have only one component but place something after the tag (the <p>text here</p> above). It is not displayed too.
Here is a JSBin showing the problem http://jsbin.com/maxen/3/edit?html,js,output
You need to either add closing </widget> tag or use self-closing syntax - <widget />. Demo here.
Related
I need to be able to wrap custom HTML around my Vue template content. As you can see below, it's not simply inserting html content using <div v-html="HtmlWrapperTopHalf"> because that will automatically close any unclosed tags. The tags will always be closed in the bottom half of the dynamic HTML. Basically, I'm looking to insert the Vue template code into my dynamic template HTML.
I also can't just assume what's in the dynamic HTML and build that inside the Vue template. This HTML comes from a RichText editor that my customers create on their own. They just insert a placeholder {{MAIN_CONTENT}} in the middle of their dynamic template and that's where the Vue Template functionality should appear.
Page.vue
<template>
<div>
//Top half of dynamic XHTML wrapper goes here
<p>Inner Content Here</p>
<ComponentA />
<ComponentB />
<!-- etc. --->
<p>More Inner Content</p>
//Bottom half of dynamic XHTML wrapper goes here
</div>
</template>
<script>
axios.get("getHtmlContent").then((result) =>{
console.log("top", result.data.HtmlWrapperTopHalf)
console.log("bottom", result.data.HtmlWrapperBottomHalf)
});
</script>
console.log
top: <div class="my-dynamic-class" id="my-unique-id"><h1>DYNAMIC TITLE</h1>
bottom: <div id="my-dynamic-footer">custom footer text</div></div>
HTML Output:
<div>
<div class="my-dynamic-class" id="my-unique-id"><h1>DYNAMIC TITLE</h1>
<p>Inner Content Here<p>
<div>Hello from ComponentA!!</div>
<div>Hello from ComponentB!!</div>
<!-- etc. --->
<p>More Inner Content<p>
<div id="my-dynamic-footer">custom footer text</div></div>
</div>
Hopefully this diagram of the concept will help:
Given that other components can be a part of this split up html content, using the render syntax to generate a slot within the content seems to be the only alternative.
render(createElement) {
return createElement(
'div', { 'class': 'hello'},
this.$slots.default
)
},
Have your axios component be built out within the render (see docs), and then use this as a slot to fill in within future components.
E.g. <ClientHtmlInject> <Comp1/><Comp2/> </ClientHtmlInjection>
I'm trying to remove the called component tag from HTML to prevent some broken CSS from external libraries and just show the inner content.
something.component.html
<div>
Hello World
</div>
another.component.html
<div>
<app-something [config]="somethingConfig"></app-something>
</div>
Then outputs:
<div>
<app-something>
<div>
Hello World
</div>
</app-something>
</div>
And I want:
<div>
<div>
Hello World
</div>
</div>
This is not possible due to the nature of web components which Stencil outputs.
What you could do instead: use the CSS rule display: contents on your component which prevents it from generating a box in the layout (see https://caniuse.com/css-display-contents, still somewhat experimental).
There are also functional components in Stencil (https://stenciljs.com/docs/functional-components) which don't generate a parent element, but those are only available within JSX, so you'll always need at least one parent Stencil component (so that you can render some JSX).
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
The way I see it - an ng-content tag with a component selector is the same thing as writing the component tag itself. For example, a project I'm doing some tasks for uses this:
<div class="sidebar-style"
[ngClass]="{
'sidebar-hidden': !showSidebar
}">
<ng-content select="car-sidebar"></ng-content> <-------this
</div>
And I don't understand, why would that code be chosen over this:
<div class="sidebar-style"
[ngClass]="{
'sidebar-hidden': !showSidebar
}">
<car-sidebar></car-sidebar> <-----is the same as this
</div>
Are there any reasons/use cases where the ng-content should be used instead of the component tag itself?
They are two different elements, with a component tag you render that component inside some other parent component. You can't put any text between a component tag if it doesn't have an <ng-content></ng-content> inside its HTML
i.e
<car-sidebar>Some Test Here </car-sidebar> wont display any text if it doesnt have
<ng-content></ng-content> in its (car-sidebar.component.html) file
Lets say we have two different components as you described
Parent1:
<div class="sidebar-style"
<ng-content select="car-sidebar"></ng-content> <-------this
</div>
Parent2:
<div class="sidebar-style"
<car-sidebar></car-sidebar> <-----is the same as this
</div>
Usage examples:
<Parent1>
<p>some random unnecessary text</p>
<car-sidebar aParameter=[aValue]></car-sidebar>
</Parent1>
will output to
<Parent1>
<p>some random unnecessary text</p>
<car-sidebar aParameter=[aValue]></car-sidebar>
</Parent1>
but
<Parent2>
<p>some random unnecessary text</p>
<car-sidebar aParameter=[aValue]></car-sidebar>
</Parent2>
will output to
<Parent2>
<car-sidebar></car-sidebar> <-----is the same as this
</Parent2>
i am trying to make a blog page with angularJS and on the message part i have a div like this.
<div class="post-content">
{{jsonPost.message}}
</div>
and inside the variable jsonPost.message i got a string like this
<p>paragraph 1</p>
<p>paragraph 2</p>
but instead creating 2 html paragraphs, instead i see the <p> texts on the screen aswell like a text. Is there a way to make them html code ? and than target them via css.
Thank you, Daniel!
Since you are using v1.2, you need to use ng-bind-html. To bypass sanitization use $sce service:
$scope.jsonPost.message = $sce.trustAsHtml("<p>paragraph 1</p>");
HTML:
<!-- bypasses sanitizaton -->
<div data-ng-bind-html="jsonPost.message"></div>
You can use ng-bind-html-unsafe:
<div class="post-content" ng-bind-html-unsafe="jsonPost.message"></div>