Render HTML Tag Vue.js - javascript

I am trying to add a render a template using the push mutation method. I want to push a section component, but instead of the template content I get the raw output of <vsection></vsection'. Can anyone help me render the actual template content and not the raw tags? I included a jsbin below.
http://jsbin.com/wurofatuve/1/edit?html,js,output

You're thinking about this a little oddly. What I think you'd be better off doing is putting a v-for on a <vsection> component.
<vsection v-for="section in sections">
{{ section.content }}
</vsection>
This way, when you push content to sections it'll out put another one. You'll also have to adjust your section component so you can use the content.
<template id="section-template">
<div class="section">
<slot></slot>
</div>
</template>
Here it is working like I think you want: http://jsbin.com/suhadidobe/1/edit?html,js,output

Related

Create a base component to be reused when creating new components

I'm putting together an application in which there are many modals. As I do not want to repeat the code of the modal, I want to assemble a base component that has the minimum structure and then with that structure to be able to assemble the different modals and to carry what I need inside (form, text, images)
An example of what I am looking to do
<app-modal-base>
<app-form></app-form>
<app-modal-base>
I hope you understand what I'm looking for. In case you can not, someone found an alternative solution?
Thanks
In your base modal template, include the <ng-content></ng-content> tag. When you display your modal, you can use it as follows:
<Modal>
<div id="mydiv">
<p> Simple paragraph </p>
<form>...</form>
</div>
</Modal>
The modal will include what you have included between the <Modal></Modal> tags at the place where the <ng-content></ng-content> tags are in the template for the base modal component. It would look like:
template: `
<div id="closeButton"></div>
<ng-content></ng-content>
`
This information is gathered from this source, and I can't seem to find official docs about this. You might have to try it out.

Include component from parent app in component contained in node_modules directory

I am working on Vue app that incorporates Vue Bootstrap Calendar, and I would like to be able to override the content of the day cell (handled by the Day.vue component) to add my own custom content inside. My thought was initially to modify the Day component to include <slot></slot> tags and pass in the custom content that way.
The problem has to do with accessing the Day component. To include the calendar in your app, you include the Calendar.vue component, which includes Week.vue, which in turn includes Day.vue. As I understand slots, I have to have the child component (Day.vue in this case) included in the component where I'm passing the data, which means it would need to be included in my own component.
If this is not possible, my other thought is to perhaps modify the library by adding another configuration prop (something like dayCustomContent) to the Calendar.vue that indicates that the Day cell content is custom content, pass that in to Calendar.vue, and then down to Day.vue, and then in the Day.vue template, have a v-if conditional based on this prop that either displays the custom content or the default cell content, something like:
<template>
<div class="day-cell" v-if="dayCustomContent">
...my custom content here...
</div>
<div class="day-cell" v-else>
...default events from my.events goes here...
</div>
</template>
I would probably then need to define a custom component to render whatever custom content I want to display, and somehow include that component within Day.vue.
So to sum up, my questions are these:
1) Is there a way to do what I need with slots?
2) For my second option, am I going down the right path? I'm open to suggestions.
UPDATE: I was able to get this done by adding a boolean customDayContent prop in Calendar.vue like so and passing it down to Week.vue and then to Day.vue:
<template>
...
<div class="dates" ref="dates">
<Week
v-for="(week, index) in Weeks"
:firstDay="firstDay"
:key="week + index"
:week="week"
:canAddEvent="canAddEvent"
:canDeleteEvent="canDeleteEvent"
:customDayContent="customDayContent"
:displayWeekNumber="displayWeekNumber"
#eventAdded="eventAdded"
#eventDeleted="eventDeleted"
></Week>
</div>
...
</template>
<script>
export default {
...
props: {
...
customDayContent: {
type: Boolean,
default: false
}
},
}
</script>
and then in Day.vue, do like I had suggested with v-if:
<template>
<div class="day-cell" v-if="customDayContent">
<custom-day></custom-day>
</div>
<div
class="day-cell"
:class="{'today' : day.isToday, 'current-month' : day.isCurrentMonth, 'weekend': day.isWeekEnd, 'selected-day':isDaySelected}"
#click="showDayOptions"
v-else
>
... existing code goes here...
</div>
</template>
The last part is referencing the CustomDay.vue component referenced in my v-if block. I want the user to be able to define the content of their own custom CustomDay.vue template in their own parent app. However, I'm having trouble trying to figure out how to do that. Following the pattern of including components already in this component, I added this in the components section of Day.vue:
CustomDay: require("../../../../src/Components/CustomDay.vue").default
? require("../../../../src/Components/CustomDay.vue").default
: require("../../../../src/Components/CustomDay.vue")
However, no matter what I try along these lines, I get an error that the relative module was not found. On top of that, I need to add it to the componentsarray only if customDayContent is true. What is the best way to do that? In a watcher or computer property, perhaps? Or another way?

Angular: Cloning ng-content elements and it's functionality

I'm trying to clone the ng-content items of a component along with any functionality added on the HTML of that content. For example, the markup using the component might look like this:
<custom-component>
<button (click)="doAThing();">A button</button>
</custom-component>
Then I set up my template for custom-component like so:
<ng-template #content>
<ng-conent></ng-content>
</ng-template>
<ng-template *ngTemplateOutlet="content"></ng-template>
<div class="second-area>
<ng-template *ngTemplateOutlet="content"></ng-template>
</div>
My expectation would be that the ng-content would get duplicated into both ngTemplateOutlet areas. What happens is that it pushes to the last outlet and ignores the first. This markup will duplicate normal markup just fine, but ng-content only move to one outlet.
Is this not possible with this technique, am I missing something obvious, or it there another way to clone the contents of ng-content along with any events attached to it?
I found this solution that worked for me. First the HTML, you'll need a directive to wrap the content in so you can reference it. You'll need to use asterisk with directive so it can be duplicated.
<custom-component>
<ng-container *customDirective>
<button (click)="doAThing();">A button</button>
</ng-container>
</custom-component>
The directive doesn't require any extra code. We just need it for a reference.
In your custom-component, you'll need to create a reference to the diretive via #ContentChild like so:
#ContentChild(CustomDirective, { read: TemplateRef }) transcludeTemplate;
Then we use the following for our custom-component HTML avoiding using ng-content tags all together:
<ng-template *ngTemplateOutlet="transcludeTemplate"></ng-template>
<div class="second-area>
<ng-template *ngTemplateOutlet="transcludeTemplate"></ng-template>
</div>
So this isn't really the same as duplicating <ng-content>, but it gives us a similar function. Apparently ng-content not multiplying is intended behavior. So this might be the best way to achieve a similar goal.

VueJs Conditional handlebars

I'm trying to use VueJs conditional rendering using handlebars in vueJs 2.0 as per their documentation but eslint is coming back with and error:
- avoid using JavaScript keyword as property name: "if" in expression {{#if ok}}
- avoid using JavaScript keyword as property name: "if" in expression {{/if}}
VueJs does not seem to be rendering it.
<!-- Handlebars template -->
{{#if ok}}
<h1>Yes</h1>
{{/if}}
If you are trying to use Vue.js syntax, the documentation outlines just a few lines down what's done for Vue.js. You would use the v-if directive.
<h1 v-if="ok">Yes</h1>
If like you mentioned, you're wanting to use Handlebars alongside Vue.js, note that both of them use the same {{ curly braces in templates. You may need to change Vue's use of the curly braces like so...
Vue.config.delimiters = ['<%', '%>'];
Either:
Using v-if to conditionally render
<h1 v-if="isVisible"> Yes </h1>
or using v-show to add a hidden attribute to that element style
<h1 v-show="isVisible"> Yes </h1>
either can be used but be careful with v-if since the element won't be in the DOM if the condition is not met.
I believe that is simply to document that the conditional does not go on a parent tag, but rather it is placed directly on the node that you want to conditionally display.
In other words its simply a comparison not part of Vue.js markup, but rather part of Handlebars.
Vue conditional rendering syntax
<h1 v-if="ok">Yes</h1>
<h1 v-show="ok">Yes</h1>
Details in original docs.
https://v2.vuejs.org/v2/guide/conditional.html#v-if-vs-v-show
Firstly, You should look at the vue documentation .https://v2.vuejs.org/v2/guide/conditional.html#v-if-vs-v-showjs and by the way, you can use "v-if" and "v-show"attributes, in flowing related to
examples.
<h1 v-if='isShow'>Test</h1>
<h1 v-show='isShow'>Test</h1>
For anyone coming here from a search trying to conditionally render inside {{ }} braces, you could always use a computed property:
import { computed } from 'vue';
<script setup>
const submitButtonText = computed(() => {
return props.formObject ? 'Save' : 'Create';
});
</script>
<template>
<form>
<button type="submit">
{{ submitButtonText }}
</button>
</form>
</template>
v-if and v-if-else work perfect for large elements, but this is great for simple one-line conditional text.

I want Handlebar {{#if}} logic inside of a Ember.Handlebars.helper

I am converting someone else's code to Handlebars.js and I'm stuck on converting this tag to its {{#handle-bar}}{{/handle-bar}} counterpart.
The previous coder used an {{#ifCond}} to toggle what 'selected'. This is my component.
{{#dropdown-item }}
{{unbound this.itemName}}
{{/dropdown-item}}
Here is the div i want converted to my component
<div class="dropdownItem" {{bind-attr value=formField_DropdownItemID}}{{#ifCond formField_DropdownItemID value}} selected{{/ifCond}} >
{{unbound this.itemName}}
</div>
My first thought was to just pop the div's logic into the the component, like the next example, but this gave me an error.
{{#dropdown-item bind-attr value=formField_DropdownItemID {{#ifCond formField_DropdownItemID value}} selected{{/ifCond}} }}
{{unbound this.itemName}}
{{/dropdown-item}}
Any suggestions?
You can set those properties to compute. The syntax would be:
{{#dropdown-item selected=computedProperty value=formField_DropdownItemID}}
computedProperty can deal with your conditional logic. The whole idea is to pull that out of handlebars anyways. :)

Categories

Resources