AngularJS load font-face on demand - html

I'm new to AngularJS. I have a web service which returns a list of cdn links for fonts. I want to use it and show some text using the fonts in run time. My client application is written in angularJS. How can I achieve this? Please help. This is what I have tried so far. How can I inject font faces on demand?
app.js (data returned by web service is shown as a list here.)
var app = angular.module( 'app', [] );
app.controller('appController', function($scope) {
$scope.fonts = [
{
"family": "Abhaya Libre",
"url": "https://cdn.rawgit.com/mooniak/abhaya-libre-font/gh-pages/fonts/AbhayaLibre-Regular.otf"
},
{
"family": "Gemunu Libre",
"url": "https://cdn.rawgit.com/mooniak/gemunu-libre-font/gh-pages/tests/fonts/GemunuLibre-Regular.otf"
},
];
});
app.html
<div ng-app="app" ng-controller="appController">
<p ng-repeat="font in fonts">
<span style="#font-face {font-family:{{font.family}}; src: url({{font.url}});}">
{{font.family}}
</span>
</p>
</div>
JSFiddle - https://jsfiddle.net/lpsandaruwan/rpffoo06/

Here is the Solution, in the style you are not putting font-family:{{font.family}};
http://pastebin.com/WmBv5XDB

Related

Binding JSON URL to IMG in Vue 3

I'm building an app in Vue 3 that lists local stores. To add and remove stores I've made a JSON file that lists them, including a URL to an image icon (SVG). The JSON file is imported in my Vue component and lists the stores correctly. However, this is not the case for the image files, see code below.
JSON
[
{
"storeName": "Kapper",
"storeId": "s0001",
"imgUrl": ""
},
{
"storeName": "Manicure",
"storeId": "s0002",
"imgUrl": ""
},
{
"storeName": "Supermarkt",
"storeId": "s0003",
"imgUrl": "../../assets/icons/021-grocery.svg"
]
VUE
<template>
<ul class="storeList">
<li class="store" v-for="data in $options.stores" v-bind:key="data">
{{data.storeName}}
<img :src="data.imgUrl"/>
</li>
</ul>
</template>
<script>
import stores from './stores.json'
export default {
stores: stores,
}
</script>
<style lang="scss" scoped>
#import './styles.scss';
</style>
Some things I found out:
Hardcoding the URL seems to work fine
Placeholders from the web also seems to work fine (e.g https://picsum.photos/200 works perfectly)
Other file extensions such as .png also don't work
Changing the directory of the icons is what worked for me in the end. Changed the icons from the "assets" folder to the "public" folder.

storybook darkmode not playing nice

So I am using storybook for my svelte + tailwind app, and I am now trying to make sure that I can toggle darkmode.
So for my tailwind.config.js I added this
module.exports = {
darkMode: "class",
and I installed this addon to storybook
https://github.com/hipstersmoothie/storybook-dark-mode
with this config .storybook/preview.js
export const parameters = {
darkMode: {
darkClass: "dark",
stylePreview: false,
},
And by looking in the DOM of the storybook iframe I can see that "dark" is applied to the body.
But when I create a component with this HTML
<div class="inline">
<div class="w-8 h-8 bg-blue-500 dark:bg-green-500" />
</div>
the box is always blue.
So I thought maybe purgecss was removing it, and so I added safelist: ["dark"] to it's options but without any luck.
So to make things more complicated I tested this component
<div class="inline">
<div class="w-8 h-8 bg-blue-500 dark:bg-green-500" />
</div>
<div class="inline dark">
<div class="w-8 h-8 bg-blue-500 dark:bg-green-500" />
</div>
and to my surprise, one of the boxes turned green.
Honestly, I am not entirely sure if this is because of svelte, storybook, tailwind, or the darkmode storybook plugin.
But I would really appreciate help if anyone has seen something similar
You could try ignoring purgecss when watching for storybook.
I am not sure about your exact setup but in my case I added a conditional in postcss.config.js for storybook to work correctly:
const isProduction =
!process.env.ROLLUP_WATCH &&
!process.env.LIVERELOAD &&
process.env.NODE_ENV !== 'development'
module.exports = {
plugins: [
require('tailwindcss'),
...(isProduction ? [purgecss] : [])
]
};
My .storybook/preview.js contains the following:
export const parameters = {
darkMode: {
stylePreview: true,
darkClass: 'dark',
lightClass: 'light',
}
}
The only thing which still doesn't work after this is the white text in dark mode, so I had to add .dark { color: white; } to my css.
I had this issue as well but it was because I defined a prefix of vc- in my tailwind.config.js file.
When I configured the addon https://github.com/hipstersmoothie/storybook-dark-mode, I used the class dark not vc-dark in .storybook/preview.js:
export const parameters = {
darkMode: {
dark: { ...themes.dark },
light: { ...themes.light },
darkClass: 'dark',
stylePreview: true
}
}
should be
export const parameters = {
darkMode: {
dark: { ...themes.dark },
light: { ...themes.light },
darkClass: 'vc-dark',
stylePreview: true
}
}
Not sure if you, (OP), have a prefix defined in your tailwind.config.js file but it's something to watch out for, if others are having the same issue.
Even with the prefix, you can still use the dark variant normally, just don't forget to use the prefix when referencing class names after the variant:
<div class="vc-bg-blue-500 dark:vc-bg-green-500" />
This happens because components are rendered inside of an iframe and storybook-dark-mode (SDM) only sets the class to "dark" on the body of the main document.
I verified this by inspecting and adding it manually. Assuming that you have darkMode: 'class' set in your tailwind config, you should see it work as soon as you set <body class="dark"> inside that iframe. This is why when OP wrapped it in a parent with "dark", it worked for that instance only.
First attempt
The question to me is how to get that class applied to the body of the iframe as well? Reading SDM docs, it implies that it would apply it to the app as well as the preview window, but that doesn't seem to happen for me.
Interestingly, there is an add-on called storybook-tailwind-dark-mode (STDM) which adds "dark" to the <html> of the iframed document, so that's good; but it's a separate button. You can have your components render in dark or light mode independent of dark mode on the app itself.
This is currently the only way it's working for me and I'd like to see/make a fork off one of these where it does both at once.
FWIW, without Tailwind, we were using a ThemeProvider from StyledComponents that leveraged useDarkMode() from SDM to then pass that down to all the StyledComponents (which we're migrating away from in favor of Tailwind). It would be nice to leverage that somehow.
Final answer
That previous paragraph gave me some inspiration. Storybook has decorators, which are basically functions that return components. We can wrap our stories with some HTML and give it a class based on useDarkMode().
Below is more or less what I ended up using and it's working great. One button to control dark mode, no need for an additional tailwind-specific dependency, and I'm still able to use my StyledComponent theming for the components that haven't been migrated yet.
.storybook/theme.js
import React from 'react'
import { ThemeProvider } from 'styled-components'
import { themeV2, GlobalStylesV2 } from 'propritary-design-library'
import { useDarkMode } from 'storybook-dark-mode'
import '../src/index.css'
const ThemeDecorator = storyFn => {
const mode = useDarkMode() ? 'dark' : 'light'
return (
<ThemeProvider theme={themeV2(mode)}>
<section className={mode}>
<GlobalStylesV2 />
{storyFn()}
</section>
</ThemeProvider>
)
}
export default ThemeDecorator
.storybook/preview.js
import { addDecorator } from '#storybook/react'
import ThemeDecorator from './theme'
addDecorator(ThemeDecorator)
export const parameters = {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
}

why the html content not shown out when running

Now i use visual studio code to do my project. I can build my code without error, but when running, it no show out the content for html file, only have show css like header abd footer. i have click button on header but cannot go to other page.Here is the sample code
code in index.html
<nav>
List
New student
Student feedback
</nav>
Vue router
const router = new VueRouter({
routes: [
{ path: '/home', component: load('home') },
{ path: '/insert', component: load('insert') },
{ path: '/update/:id', component: load('update') },
{ path: '/feedback', component: load('feedback') },
{ path: '*', redirect: '/home' }
]
});
File name and type: _home.html, _insert.html, _update.html, _feedback.html
Can help me see the problem, thank you
I don't think you should edit directly to index.html as Vue is Single Page Application (SPA) framework. Instead, you should use Vue Component for each page.
This video might help you to figure out how to use Vue and Vue Router properly: https://youtu.be/nnVVOe7qdeQ
Edit:
For sake of clarity, Let me build simplified diagram of Vue project for you.
First of all, make sure you create the project via vue cli. It guides you to build your new vue project better.
Let's say we have 3 pages:
Home
About
Another
Each page has its own CSS, HTML (we call it template), and JavaScript in one file, the .vue file. To connect them, we need a first entrance, main.js. Inside of it, we can configure the router.
Inside main.js
import Vue from "vue";
import VueRouter from "vue-router";
import App from "./App.vue";
import HomePage from "./HomePage.vue";
import AboutPage from "./AboutPage.vue";
import AnotherPage from "./AnotherPage.vue";
// This is your router configuration
Vue.use(VueRouter);
const router = new VueRouter({
[
{ path: "/", component: HomePage },
{ path: "/about", component: AboutPage },
{ path: "/another", component: AnotherPage },
],
mode: "history",
});
// Initialize Vue App
new Vue({
router,
render: h => h(App),
}).$mount("#app");
Then, we need to create App.vue and put <router-view /> inside of it.
Inside App.vue source file
<template>
<div id="app">
<router-view />
</div>
</template>
<script>
export default {
// Keep this empty. Except if you
// need to add sidebar or any else.
}
</script>
Now you're ready to create those three pages
Every pages looks like this:
<style scoped>
// Your CSS here
</style>
<template>
<div>
<!-- Your HTML here -->
</div>
</template>
<script>
export default {
data() {
return {
// Your reactive data here
}
},
mounted() {
// Your script here
},
methods: {
// Your functions here
},
}
</script>
That's all I can explain, hope it helps. If I missed something, please don't hesitate to tell me. Thank you!

Nested v-for loops using p tag doesn't work in Vue.js

I want to nest 2 v-for loops. It should be quite simple, but it's not working and I have no clue why.
When I loop through the users and display their names, this is working fine. When I take the first element from the session-array and display it's name, this is also working fine.
However, when I want to cycle through the session-array in a nested v-for loop, the array seems to be empty. Why is this?
<p v-for="entry in user">
{{entry.name}} //this is working fine
{{entry.session[0].name}} //this is also working fine, so "session" is an array with elements that have the property "name"
<p v-for="session_entry in entry.session"> //this v-for is not executed, as if entry.session would be empty
{{session_entry.name}}
</p>
</p>
data: {
user: [{
name: 'test2name',
session:[
{name:'sessionname'},
{name:'sessionname2'}
]
}]
}
According to this code snippet it should be working. What did I miss?
https://www.codegrepper.com/code-examples/javascript/vuejs+nested+v-for
When i change the outer p to div it works fine as below :
Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
el: '#app',
data: {
user: [{
name: 'test2name',
session: [{
name: 'sessionname'
},
{
name: 'sessionname2'
}
]
}]
}
})
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app" class="container">
<div v-for="entry in user">
{{entry.name}}
<p v-for="session_entry in entry.session">
{{session_entry.name}}
</p>
</div>
</div>
Nesting p tags is not allowed in HTML
Vue compiler (which processes your template) somehow knows this and compiles into something like this:
<p v-for="entry in user">
{{entry.name}}
{{entry.session[0].name}}
</p>
<p v-for="session_entry in entry.session">
{{session_entry.name}}
</p>
...which leads to an error "entry is undefined but referenced during render"
You can check yourself by pasting your templete into vue-compiler-online and look at the AST on the right
BTW you should always check your browsers Dev Tool console for useful messages like this when something doesn't work as expected...

generating with angularJS HTML from JSON-Objects

I'm developing an app with the Ionic framework based on angularjs. I'd like to let generate HTML elements or components from a JSON file. These are buttons, lists, labels, etc.
My JSON objects look like this:
[
{
"category": "communicationPage",
"type": "Button",
"id": "communicationButton",
"icon": "ion-chatboxes",
"name": "Communication",
"onClick": "window.location.href='communicationPage.html'",
"ngclick": "open()",
"ngcontroller": "openctrl",
"color": "white",
"background-color": "#ff5db1",
"font-size": "20px"
},
{
"category": "servicePage",
"type": "Button",
"id": "serviceButton",
"icon": "ion-briefcase",
"name": "Service",
"onClick": "window.location.href='servicePage.html'",
"color": "blue",
"background-color": "#009900",
"font-size": "26px"
}
]
I can access via my Controller on the JSON file and parse as follows:
myApp.controller('generateHTMLCtrl', function ($scope, $http) {
$http.get('myJSONFile.json').success(function(data){
$scope.components = data;
//...
});
});
The code translates of course nothing.
My question is, how can I adapt my JavaScript code so that from a
JSON object following HTML element is generated?:
<button style="color: blue; background-color: #ff5db1; font-size: 20px" onclick="window.location.href='communicationPage.html'" id="communicationButton" class="button">
<i class="ion-chatboxes"></i> <br> Communication
</button>
Once my JSON object is located always in the JSON file, should always be created the HTML element on the page.
The second question is how I can position this generated HTML
element just in my HTML page?
I want that the HTML element is generated between the responsive grid element, such as:
<div class="row responsive-sm">
<div class="col">
<!-- The Button should be generated hier-->
</div>
</div>
The third and final question is how I can let generate the HTML
element on the appropriate page? Such as: If in JSON object the key-value pair of "category": "communicationPage" occurs should the corresponding HTML element be created on 'communicationPage.html'
I would look forward to an example. Many thanks.
For the two first point, use the data-binding and ng-repeat : directive
<div class="row reponsive-sm" ng-controller="generateHTMLCtrl">
<div ng-repeat="component in components">
<button style="color : {{component.color}}; background-color : {{component.background-color}} ... ">
</button>
</div>
</div>
For the last point, I'm not sure if it's possible with AngularJS ...