I want to build a multi-step form, where each step is its own tab and the user can go forward/backwards through the form. Each tab has a header, content and navigation buttons.
In my form component, I have an array of all components (each represents a step in the form) and I want to loop through it in the form's template, so that each step has the same structure and if I want to change that structure I should only change the code in the loop, as it's the same for all steps.
This is the array in the form.component.ts:
steps = [
LanguageComponent,
CodeComponent,
HardwareComponent,
SubmissionComponent
]
Or should it be:
steps = [
new LanguageComponent,
new CodeComponent,
new HardwareComponent,
new SubmissionComponent
]
?
This is the pseudo form.component.html:
<div id="tabs">
<div class="tab" *ngFor="let step of steps" id="{{step.header}}">
{{ step.header }}
<app-step></app-step>
{{ buttons }}
</div>
</div>
Each step component has header property.
That way, in order to change the structure of the tab, I only have to change it here once, if the header and buttons go inside each components' template, then I will have to change each component's template, if I want to change the tab structure.
How would you do this, is there a better way to achieve this structure?
Thank you!
You need a placeholder component that houses the form tab structure. Then like you said you only have 1 place that you would have to change the layout.
AppFormTabComponent.html
<ngb-tabset>
<ngb-tab>
<ngbTemplate>
<language-component [form]="form"></language-component>
</ngbTemplate>
</ngb-tab>
<ngb-tab>
<ngbTemplate>
<code-component [form]="form"></code-component>
</ngbTemplate>
</ngb-tab>
...
</ngb-tabset>
Then you would only call your AppFormTabComponent once to use it
form.component.html
<app-form-tab-component [form]="form"></app-form-tab-component>
And your form would be in the app.component.ts page and you would pass the form in to each one of your templates.
Related
<div class="flex">
<div class="layout-row layout-align-end-center">
{{#paper-button href="overview" raised=true primary=true}}Overview{{/paper-button}}
{{#paper-button href="incomes"}}Incomes{{/paper-button}}
{{#paper-button href="expenses"}}Expenses{{/paper-button}}
{{#paper-button href="settings"}}Settings{{/paper-button}}
</div>
</div>
So I am trying to set the raised=true whenever I am on certain page/template. The above code is from my application template. Is there any way of doing this using JS/Ember or should I just do it manually in each of my templates?
I think the best way to go is to write a custom component wrapping paper-button. ember-route-helpers gives you nice helpers to do that:
{{#paper-button
onclick={{transition-to #route)
href=(url-for #route)
raised=(is-active #route)
primary=(is-active #route)
}}
{{yield}}
{{/paper-button}}
Then you can use that component with {{#your-component route="settings"}}Settings{{/your-component}}.
It's important to understand that you should pass both the action and the href. Because then when people click on the button it will make a transition and dont reload the entire page, but rightlick->open and screenreaders are are not broken.
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.
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?
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
I have a nested route that looks like:
/products
/products/:productId
And the /products template renders with a sidebar listing all the products, and a "main" content <div> in the center that is populated with a specific product when clicked. ie:
<div id="productsSidebar">
... navigation tree ...
</div>
<div id="mainContainer">
{{outlet}}
</div>
However, I would like for the {{outlet}} to be replaced with a message like
Please select a product to the left.
When there is no child route, ie. we're just looking at /products and the main <div> is otherwise completely empty.
I haven't found any reference/tutorial demonstrating if this is possible - is there a standard way to render a "default" block of HTML if there no outlet available?
You can use the products index route template to display that html text. You may need to generate the route with something like ember g route products/index