I have root selector:
<body>
<my-app>
Loading...
</my-app>
</body>
In him loaded component with template:
#Component({
selector: 'my-app',
template: `
<p>It is nested content:</p>
<div class="content">
<nested-selector></nested-selector>
</div>`
})
Now I want to download the content in nested-selector:
#Component({
selector: 'nested-selector',
template: `<p>{{content}}</p>`
})
export class Mycomponent{
public content = "qwerty12345";
}
As a result, appended in the end an string:
<nested-selector _ngcontent-rbv-2="">qwerty12345</nested-selector>
As a result, we get the following page:
<body>
<my-app>
<p>It is nested content:</p>
<div class="content">
<nested-selector></nested-selector>
</div>
<nested-selector _ngcontent-rbv-2="">qwerty12345</nested-selector>
</my-app>
</body>
Although page should look like this:
<body>
<my-app>
<p>It is nested content:</p>
<div class="content">
<nested-selector>qwerty12345</nested-selector>
</div>
</my-app>
</body>
Why is this happening? Why he creates a new selector? How to make it work properly?
EDIT:
I attached the main project files to uncover the essence of the problem:
https://plnkr.co/edit/DsDpXG72bjpyaWfPc1S0?p=preview
I'm pretty sure you HTML is invalid.
.
I tried to reproduce in this Plunker but it shows the desired behavior.
Related
Is there any way to hide the main div in a Vue app that is builded by Vue-CLI? I have tried appending display property but it didn't resolve the issue. I am trying to hide it inside the Channels component of mine. My main component looks like this :
<template>
<div id="app">
<Channels/>
</div>
</template>
<script>
import Channels from './components/Channels'
export default {
name: 'App',
components: {
Channels
}
}
</script>
You can use <template> tag.
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<template>
<p>
Am I wrapped around Div or Template?
</p>
</template>
</div>
<script>
new Vue({
el: "#app"
})
</script>
You can inspect the parent of p tag in developer tools. It is div instead of template
you mean <div id="app">?, you can delete it directly, but you should maintain that three is only one root in <template>
let's say I've got the following basic component with two slots:
// my-component.component.ts
#Component({
selector: 'my-component',
template: `
<div class="my-component">
<div>
Title:
<ng-content select="my-component-title"></ng-content>
</div>
<div>
Content:
<ng-content select="my-component-content"></ng-content>
</div>
</div>`
})
And into the second slot ('my-component-content') I want to insert regular Angular 2 component...
<div class="app">
<my-component>
<div class="my-component">
<div>
Title:
<my-component-title>
This is the Component title!
</my-component-title>
</div>
<div>
Content:
<my-component-content>
<some-regular-angular2-component></some-regular-angular2-component>
</my-component-content>
</div>
</div>
</my-component>
</div>
Where 'some-regular-angular2-component' is a selector of some Angular 2 component...
#Component({
selector:'some-regular-angular2-component'
})'
Problem is that 'some-regular-angular2-component' is never transcluded into ng-content second slot...Only regular HTML works for me...Of cource I tried to set 'some-regular-angular2-component' into [directives] of parent component, but Angular 2 component is not recognized inside of the ng-content...Or does this work for you?
You need to add <ng-content></ng-content> to the view (template) of <my-component-content> If <my-component-content> doesn't support transclusion, its children won't be shown. The <ng-content> tags in your code apply only to elements that match directly, but not their children.
Just to answer my question, yes, angular 2 transclusion supports inserting of Angular 2 components. I had stupid typo in the code.
Yes it does. It is now called content projection. See this example of a modal dialog with multiple slots.
I've got a component that has it's default template:
import {Component} from 'angular2/core';
#Component({
selector: 'my-component',
template: `
<div class="container">
<div class="content">
<div *ngIf="contentRef.childNodes.length == 0">DEFAULT: <b>{{contentData}}</b></div>
<div #contentRef><ng-content select=".content"></ng-content></div>
</div>
</div>
`
})
export class MyComponent {
contentData = "DATA";
}
I would like a user to be able to specify his own templates for some parts of the component when using it. So it can be written as follows:
import {Component} from 'angular2/core';
import {MyComponent} from './my.component';
#Component({
selector: 'my-app',
directives: [MyComponent],
template: `
<my-component></my-component>
<br/>
<my-component>
<div class="content">
CUSTOM: <i>{{contentData}}</i>
</div>
</my-component>
`
})
export class AppComponent { }
It produces the following markup:
<my-app>
<my-component>
<div class="container">
<div class="content">
<!--template bindings={}--><div>DEFAULT: <b>DATA</b></div>
<div></div>
</div>
</div>
</my-component>
<br>
<my-component>
<div class="container">
<div class="content">
<!--template bindings={}-->
<div><div class="content">
CUSTOM: <i></i>
</div></div>
</div>
</div>
</my-component>
</my-app>
So the component's 'contentData' property is not rendered within the custom template. Is it possible to provide the custom template with a specific binding context somehow? Or is there a better way to implement the case with a custom user template?
How to realize website with hundreds of pages in Angular2 shows an approach.
This is no official solution and to me it currently looks like this is likely to break before the final release.
Angular2 has a strong tendency to statically building and resolving the bindings.
Either you can work with DynamicComponentLoader or you don't build on Angulars binding features for dynamically added content.
I'm using angular 2 to create a page using different components. My layout is kinda like this:
#Component({
selector: 'my-app',
template: `
<x-header></x-header>
<div class="col-md-1">
<x-sidebar></x-sidebar>
</div>
<div class="col-md-6">
<x-table></x-table>
</div>
`,
directives: [HeaderComponent, SidebarComponent, TableComponent]
})
export class AppComponent {}
that is my main component that gets loaded from the index.html - the other components contain the tags and css pertaining to their parts. I'm adding bootstrap.min.css in the index.html and I wanted the grid system to be applied to the whole page, so I could have the components fit together. Yet, this is the layout of the current page.
As you can see the table is being rendered from the start of the page, and it goes under the sidebar and the header. I'm not sure if it's important, but I plan to add a "toggle nav bar" button somewhere.
EDIT: My question is, why are the components fitting in together? Why is the table underneath the header and sidebar? Why isn't the bootstrap grid system working?
This seems more of a css issue.
Bootstrap grid system works like count of 12 meaning if you have two elements on the page in a block then if first element is col-md-4 then second should be col-md-8 to fit in horizontally.
#Bootstrap grid system.
In your case it might be possible at template:
#Component({
selector: 'my-app',
template: `
<x-header></x-header>
<div class="col-md-3"><!-- change to col-md-3 -->
<x-sidebar></x-sidebar>
</div>
<div class="col-md-9"><!-- change to col-md-9 -->
<x-table></x-table>
</div>
`,
directives: [HeaderComponent, SidebarComponent, TableComponent]
})
For header you have to inspect if that element is statically positioned.
You're missing the parent div with class "row", change the code to this:
#Component({
selector: 'my-app',
template: `
<x-header></x-header>
<div class="row">
<div class="col-md-1">
<x-sidebar></x-sidebar>
</div>
<div class="col-md-6">
<x-table></x-table>
</div>
</div>
`,
directives: [HeaderComponent, SidebarComponent, TableComponent]
})
export class AppComponent {}
This may sound like a real noob question, but I'm pretty new to MVVM... or even MVC in JS, so sorry in advance.
I'm playing about with vue.js, and loving the simplicity of it so far. But for what I am trying to do, I think I need to go about it a different way.
I want to nest Vue instances/elements inside each other, but of course, the parent will then use the child when it reads through the DOM on init.
For the sake of arguments, below is an example of what I mean, I am not doing anything like this, but this is the simplest way to example what I mean:
<body>
{{ message }}
<div id="another">
{{ message }}
</div>
</body>
Then my JS for example would be:
new Vue({
el: "body",
data: {
message: "I'm the parent"
}
});
new Vue({
el: "#another",
data: {
message: "I'm the child"
}
});
The outcome would be:
<body>
I'm the parent
<div id="another">
I'm the parent
</div>
</body>
Now I completely understand why it is doing this and in fact, it should do this, but my example is just trying to illustrate how I would do something like this?
In my real life project, I have a v-class on my body that changes when stuff happens in the body (in numerous places) but of course my body will also want other instances of vue that do other stuff.
how would I go about nesting? Is there feature in vue to deal with this? Do I need to deal with components? Or maybe, fetch the body from within a child element (e.g. like jQuery would with $("body")) then manipulate it within the Vue instance?
Hope this question isn't too stupid and someone can point me in the right direction.
Thanks
Think components.
http://vuejs.org/guide/components.html
Create a Vue instance on the body as you have above, but anything nested in that is a component. Pass data via props.
Passing in data via props is only one way to do it. Nesting components and inheriting from the parent works fine as well.
Example: http://jsfiddle.net/hajkrupo/3/
<encapsulated-component inline-template>
<header>
<cart-status></cart-status>
</header>
<cart></cart>
</encapsulated-component>
You can do this with <slot> tags. Here is an example.
1.So, first, you need to do is creating a basic layout component, like this.
You need to add <slot> tag whereever you want. Very important think is the name attribute on <slot> tag.
var basicLayout = Vue.component("basic-layout", {
template: `
<div class="basic-layout">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
`
});
2.Then create your custom component. I created myHeader component to show you, how it works.
var myHeader = Vue.component("my-header", {
template: `
<div class="header">
<ul>
<li>HOME</li>
<li>ABOUT</li>
<li>CONTACT</li>
</ul>
</div>
`
});
3.Put this sample code in your HTML file.
To put some content in current slot, just use the slot attribute in your component or your tag.
<div class="app">
<basic-layout>
<my-header slot="header"></my-header>
<p>Content in <main> tag</p>
<p slot="footer">Content in footer</p>
</basic-layout>
</div>
4.The result will be like this:
<div class="app">
<div class="basic-layout">
<header>
<div class="header">
<ul>
<li>HOME</li>
<li>ABOUT</li>
<li>CONTACT</li>
</ul>
</div>
</header>
<main>
<p>Content in <main> tag</p>
<main>
<footer>
<p>Content in footer</p>
</footer>
</div>
</div>
Please, see the documentation in official page of Vue.js
Just click link here for more info.
Here is example in jsfiddle