I'm an angular novice, currently building an angular2 app.
What I want to do is generate a series of DOM components from the following object data:
// Class construct with alphabeticalized properties
export class Screens {
screens: Array<Object>;
}
export var screenData: Screens = {
// Lists all of the audio files in the course
screens: [
{
id: 0,
template: 'templateURL-0.html',
css: 'templateURL-0.css'
},
{
id: 1,
template: 'templateURL-1.html',
css: 'templateURL-1.css'
},
{
id: 2,
template: 'templateURL-0.html',
css: 'templateURL-0.css'
}
]
};
I want the end result to be something similar to the following where template 0 will be displayed twice, and template 1 once; in order:
<app-screen></app-screen> <!-- templateURL-0.html content -->
<app-screen></app-screen> <!-- templateURL-1.html content -->
<app-screen></app-screen> <!-- templateURL-0.html content -->
I read the tutorial on Structural Directives and I think I need to implement something along those lines, however I'm honestly feeling a little lost on the best approach.
Ideally I would like to have something like:
<app-screen *ngFor="let screen of screenData.screens"></app-screen>
Which would then somehow set the template URL depending on what screenData.screens.template is.
Or should I do something like this? (unsure if correct syntax)
<div *ngFor="let screen of screenData.screens" [ngSwitch]="screenData.screens.template">
<app-screen-template1 [ngSwitchCase]="'templateURL-0.html'"></app-screen-template1>
<app-screen-template2 [ngSwitchCase]="'templateURL-1.html'">Ready</app-screen-template2>
</div>
Note: I will never change the templateURL reference.
I found that the best method to achieve this is to implement routing with the built in RouterModule.
So in the end I have the following in my class, where the template property is a url path / url segment.
// Class construct with alphabeticalized properties
export class Screens {
screens: Array<Object>;
}
export var screenData: Screens = {
// Lists all of the audio files in the course
screens: [
{
id: 0,
template: 'template/template-0'
}
]
};
Then when I want to load / instantiate this template, all I have to do is navigate to this url using something like:
<!-- Goes to localhost:4200/template/template-0 -->
<button [routerLink]="[screen.template]"></button>
Where screenis a bound variable in my .ts.
More on routing and navigation here.
Related
I am using Markdown file to generate pages for gatby. In order to control the style of pictures, I use html syntax. However, the page generated by gatsby does not display the html part.
This is my markdown file:
---
......frontmatter......
---
......content......
<table>
<tr>
<td><img src="./images/2018/zotero/ZoteroWebDAV.png"></td>
<td><img src="./images/2018/zotero/ZoteroExts.png" width=100%></td>
</tr>
</table>
......content......
Everything else is rendered normally, however, neither the table nor the pictures in it are displayed. Here is my gatsby-config.js.
{
resolve: `gatsby-transformer-remark`,
options: {
excerpt_separator: `<!-- endexcerpt -->`,
plugins: [
// 'gatsby-remark-relative-images',
{
resolve: `gatsby-remark-images`,
options: {
maxWidth: 1200,
},
},
{
resolve: `gatsby-remark-image-attributes`,
options: {
dataAttributes: true
}
},
],
},
},
What can I do to make the html part in Markdown render normally?
You can use as well the built-in dangerouslySetInnerHtml property or any markdown parser like markdown-to-jsx.
Using the first approach, following Gatsby's guides:
import React from "react"
import { graphql } from "gatsby"
export default function Template({data}) {
const { markdownRemark } = data // data.markdownRemark holds your post data
const { frontmatter, html } = markdownRemark
return (
<div className="blog-post-container">
<div className="blog-post">
<h1>{frontmatter.title}</h1>
<h2>{frontmatter.date}</h2>
<div
className="blog-post-content"
dangerouslySetInnerHTML={{ __html: html }}
/>
</div>
</div>
)
}
export const pageQuery = graphql`
query($id: String!) {
markdownRemark(id: { eq: $id }) {
html
frontmatter {
date(formatString: "MMMM DD, YYYY")
slug
title
}
}
}
`
Because you haven't shared your query I've used the one in the guide but tweak it as you wish. As you can see, everything that is in the end of the frontmatter is html:
<div
className="blog-post-content"
dangerouslySetInnerHTML={{ __html: html }}
/>
Using the second approach, and following the previous query structure, the html should be rendered as:
import Markdown from 'markdown-to-jsx';
import React from 'react';
<Markdown>{html}</Markdown>
If there's any hindrance I'd say that the second approach is better because, as the dangerouslySetInnerHTML name suggests, you are potentially exposing your site to XSS (Cross-Site Scripting), while the second approach sanitizes the implementation.
I have this tab system, which works perfectly for me. I am learning VueJs. I have a concern
regarding components and/or templates. My concern is:
Using any tab windows as an example,how do I add two components inside a tab,I mean
one of its windows or sections.
Any help,please?
This is my codepen:
https://codepen.io/luis-tavarez/pen/dyOeRwO
It would be worth checking out Vue's Single File Components.
Using the layout you already have in place, you could add additional components to a tab by doing the following. Let's assume the new component will be named Custom.
Add an additional router-view to your HTML:
<section class="mainBody">
<router-view name="header"><button>asaaasas</button></router-view>
<router-view name="content"></router-view>
<router-view name="custom"></router-view>
</section>
Add a new template block to Home, for example above line 43 where you've described the Header template:
const Custom = {
template: `
<section class="content">
<div>
<h1>Here is your new custom component</h1>
</div>
</secion>
`
};
Update Components in your Routes description:
{
path: "/three",
name: 'three',
components: {
header: Header,
content: contentThree,
custom: Custom
},
props: {
header: true,
content: false
}
},
And here it is rendered:
I am trying render a component using props. But only works when content props is not a component.
Here is an example: https://jsfiddle.net/eugenio4/onf54vt5/
// register modal component
Vue.component('component', {
template: '<span class="component-tag">This is component</span>',
})
// start app
new Vue({
el: '#app',
data: function (){
return {
test1 : '<label>this is label</label>',
test2 : '<component></component>' //this doest work
}
}
})
<!-- app -->
<div id="app">
<span v-html="test1"></span>
<span v-html="test2"></span>
</div>
Is this possible?
No, You can not do this using v-html, as documentation clearly points out:
Note that the contents are inserted as plain HTML - they will not be compiled as Vue templates.
The contents are inserted as plain HTML - data bindings/vue components are ignored. Note that you cannot use v-html to compose template partials, because Vue is not a string-based templating engine. Instead, components are preferred as the fundamental unit for UI reuse and composition.
I have a small set of icons i want to call as a custom image prop depending on what type of item the component is. Code looks like this:
Vue.component('otherArticles', {
template: `
<!-- Component -->
<li>
<img :src="icon.text && icon.video" alt="icon">
<a :href="url">{{ Title }}</a>
</li>
`,
props: {
title: String,
url: String,
icon: [
{
text: "/resources/img/icons/text-icon.svg",
video: "/resources/img/icons/video-icon.svg"
}
]
}
});
Ideally in my html I would like to call them like this:
<!--Component with text icon-->
<other-articles
icon='text' <!-- how i'd like to call the text icon as img src -->
url="."
title="Text article title">
</other-articles>
<!--Component with video icon-->
<other-articles
icon='video' <!-- how i'd like to call the video icon as img src -->
url="."
title="Video article title">
</other-articles>
The img src binding is incorrect I know, i'm using it as an example of how i'm thinking it should be done, but I'm looking for any and all recommendations on how to do this correctly so I can call it the html as the example shows.
I only have these two icons and the src location for each may change but i would like to call it the same way even if i have to update the src location for either one in the future, keeping the html calls the same or similar. Any help would be appreciated. Thanks
First start by declaring your icon list as the following in your data function:
data() {
return {
iconList: {
text: '/resources/text.png',
video: '/resource/video.png',
}
};
}
Make sure to remove the list and rename the object, as you cannot have a prop and an entry in data with the same name. Then add your definition for icon to your props section as the following:
props: {
icon: {
type: String,
required: true,
},
},
This tells Vue to typecheck the prop as a string, and warn when it's not present or not a string.
Now you need to update your template function to use this new prop as an key to lookup the related icon:
template: `
<img :src="iconList[icon]"/>
`,
Now you can use your component as <comp icon="video"/>
I am trying to use multiple UI-views in my AngularJS app and it is not working as expected. The app is a dashboard.
My directory structure is as follows:
index.html
app/
app.js
dashboard/
dashboard.html
dashboard.js
partials/
business.html
items.html
orders.html
sales.html
login/
login.html
login.js
The problem that I am having is that my index.html file has the following line of code:
<div ui-view></div>
The above line enables my application to show the login.html page and dashboard.html page. Now I want to be able to have partial views in my dashboard.html page and so I have also put the same line of code
<div ui-view></div>
in order to be able to embed partial views in my dashboard page. Instead of embedding though, the page instead just redirects. So for example if I am in my dashboard.html and click on a navigation item such as 'business', I am redirected to partials/business.html instead of the content being embedded.
1) Can I have multiple ui-views embedded within each other?
2) Am I correctly embedding the partial views?
I have scoured the internet but cannot find a solution. Thanks in advance for the help!
You can definitely have multiple embedded views.
Check out these AngularJS UI-Router tutorials: Nested Views and Multiple Named Views.
Let me know if you still have issues after looking them over.
You can define a ui-view inside another ui-view. I have implemented it in the following manner and its pretty straight forward.
Inside index.html I have code:
<div ui-view=""></div>
Then inside user.html I have code
<div ui-view=""></div>
And I have defined a config for displaying my views as
.config(function($urlRouterProvider, $stateProvider) {
var users = {
//Name must be in format Parent.Child
name: 'users',
url: '/user',
templateUrl: 'users/user.html',
controller: 'usersHandler',
data: {
pageTitle: 'Welcome to Users'
},
},
createUsers = {
name: 'users.createUsers',
url: '/createUser',
templateUrl: 'users/createUser.html',
data: {
pageTitle: 'Create Users'
}
},
listUsers = {
name: 'users.listUsers',
url: '/listUsers',
templateUrl: 'users/userLists.html',
data: {
pageTitle: 'Users listing'
}
},
getUserDealer = {
name: 'users.getUserDealer',
url: '/getUserDealer',
templateUrl: 'users/getUserDealer.html',
data: {
pageTitle: 'Users dealer listing'
}
},
editUser = {
name: 'users.editUser',
url: '/editUser',
templateUrl: 'users/editUser.html',
data: {
pageTitle: 'Edit User'
}
};
//Similarly define all the combination you want to separate
//add routes to stateProvider
$stateProvider
.state('users', users)
.state('users.createUsers', createUsers)
.state('users.listUsers', listUsers)
.state('users.getUserDealer', getUserDealer)
.state('users.editUser', editUser);
$urlRouterProvider.otherwise('/user/listUsers');
});
Whats happening is this that user.html is my parent file which is loaded inside index.html and editUser.html, getUserDealer.html and userLists.html etc are its children which I load within user.html using ui-view.
And I provide the links for nested pages as:
<ul class="nav navbar-nav">
<li>NEW USER</li>
<li>GET USER</li>
</ul>
This can be extended to additional parents and their children as per the need.
Hope it helps!!