How to import .html fragment using es6 syntax in TypeScript - import

How to import an HTML template from a relative path like this:
import customSelectHtml from "./custom-select.html!text";
TypeScript compiler complains that it cannot find module. I was trying to create an ambient module definition, but it doesn't allow relative paths in module names. I am using SystemJS as a module loader.

I'm not using typescript, but I do use ES6. Might be useful for you.
The way that I solve this is by declaring template strings using ` ` quotes. It works fine for me, I would be happy to know if someone thinks this is a bad habbit.
below a snippet with Angular(-ui-router).
index.js
var indexTemplate = `
<div>
<h1>{{ Index page }}</h1>
</div
`
export {indexTemplate}
config.js
import { indexTemplate } from './index.js'
function config($stateProvider){
$stateProvider.state('index', {
url: '/',
controller: 'indexController',
template: indexTemplate
})
}
For completeness, this assumes indexController is defined elsewhere. Also, this config function is exported to a place where app is defined. But that all is not related to the question.

It is impossible.
Due to the definition of what is module in typescript, and as far as I know in ES6 javascript (import). Module cannot be html. The common approach is to import a javascript module that exports a string containing html, css, whatever. But that is not importing of the file with raw html.
Maybe you want to have a look at html imports also, but that is completely different thing.

You can import it using require syntax
1) Create app.d.ts file and require definition so typescript know this is function. (you don;t need to add any addition library, systemJs support require syntax)
declare function require(params:string): any;
2) Now you can import your html using
var template = require('./custom-select.html!text')
I found it even better because you can use require inline
var directive = {
template: require('./custom-select.html!text'),
scope: {}
}

I don't know about SystemJS, but this is definitely possible with Webpack and the html-loader

Related

How to perform DOM manipulation using pyscript

I understand that pyscript can be used as a client side scripting language.
Is there a way to interact with the DOM by using CSS selectors, such as we have in javascript.
Something like :
nav_bar = get_element(".nav-bar")
Yes, you can call JavaScript functions and access globals from Python. Import the js namespace:
import js
or
from js import document
Then you can call functions like this:
<body>
<div id="msg">Loading page ...</div>
<py-script>
from js import document
msg = document.getElementById("msg")
msg.innerHTML = 'Hello world'
</pyscript>
</body>
The function get_element() is not a standard JavaScript function. It is a function located in libraries such as Telerik. Normally you can call those functions from Python provided they are not doing something special with namespaces and the library is loaded before PyScript. You can use normal JavaScript functions from Python to set CSS styles such as:
document.getElementById("msg").style.color = "blue"

how to load external css file with lit

Although lit provide some ways to deal with css, however I have some existing css files which I would like to use in some components, what should I do?
I have read this page https://lit.dev/docs/components/styles/ but now helpful with existing css files.
My recommendation is: Don't.
The ShadyCSS polyfill doesn't support external style sheets.
External styles can cause a flash-of-unstyled-content (FOUC) while they load.
The URL in the href attribute is relative to the main document. This is okay if you're building an app and your asset URLs are well-known, but avoid using external style sheets when building a reusable element.
External css files should only be loaded in your html file (index.html most probably).
The css should be bundled with your element.
An alternative for reusabilty would be to export shared styles and import them in your styles properties as follows:
static styles: CSSResult[] = [
// language=CSS
AnimatedStyles,
ShadowStyles,
css`
[...]`;
And import from a shared file.
export const ShadowStyles = css`
[...]
`;
export const AnimatedStyles = css`
[...]
`;
That way, they are also loaded only once.
Modern method: Only work with chromium based browser.
Read more Using CSS module scripts
import styles from './my-styles.css' assert { type: 'css' };
class MyEl extends LitElement {
static styles = [styles];
}
Other solution:
By using vite build tools:
import style from "./style.css?inline";
class MyEl extends LitElement {
static styles = unsafeCSS(style);
}

How babel and JSX related or differ?

I am learning on React JS and I have got information on JSX and babel. But I am not getting clarity on how these are helping React and how these or differ from each other
React JS
while building an app using React, you can create the components/views in two ways
using standard React object and methods
using JSX
JSX
JSX is a separate technology from React and completely optional while building React application, however it makes life much easier when you combine JSX with React.
Let's see how :
Approach 1 : standard React way
(function() {
var element = React.DOM.div({}, "Hello World");
ReactDOM.render(element, document.getElementById("app"));
})();
The above code can be found at this link.
Here, you just need to include the react and react-dom library to your page.
Nothing else is required. No JSX, no Babel.
Approach 2 : JSX way
(function() {
var HelloWorld = React.createClass({
render : function() {
return (
<div> Hello World </div>
);
}
});
var element = React.createElement(HelloWorld, {});
ReactDOM.render(element, document.getElementById("app"));
})();
The above code can be found at this link.
Note the difference here: <div> Hello World </div> is used inside JavaScript. This is called JSX syntax.
Now, compare the JSX approach with the vanilla JavaScript approach:
With JSX, You can add many more HTML like elements inline, just like standard HTML, to create the view layer.
Without JSX, the code can get messy because of the multiple layers of elements required to create HTML in JavaScript.
Babel
Now the question is, who understands JSX?.
Here We need a transpiler that understands JSX and converts it to a format that can run on browser. Babel does just this job.
Transpiling
Transpiling can be done two ways
Browser based/client side transpiling (use only for development
purpose)
include this file as a script tag
use type="text/babel" on your script tag which loads your JSX
Here's the sample code
Server based transpiling - e.g. Babel
You can use different tools like webpack etc.
Here's some sample code.
Hope this helps.
tl;dr;
JSX is an easy syntax to represent markup in your code, which Babel converts to pure JavaScript.
Long version:
JSX is a syntactical convention which aims to make element structure definition easier in a React Component's code. This XHTML-like syntax which you write inside your components gets converted into JavaScript (not very different from Hyperscript) by Babel.
A very simple Hello World component written in JSX:
class HelloWorld extends Component{
render(){
return <div><h1>Hello World!</h1></div>
}
}
And the equivalent in pure JavaScript:
class HelloWorld extends Component{
render(){
return React.createElement(
"div",
null,
React.createElement(
"h1",
null,
"Hello World!"
)
);
}
}
Do note that the above example is abbreviated to keep the focus on the JSX part.
You would soon learn that Babel actually lends a lot more power to the React world than mere JSX transpilation. It allows you to use a lot of cool new ES6/7 features right now.

Scala templates import reusable blocks (Play2)

I'm using Play framework 2.2.4 and Scala templates. I have created base Scala template with many code blocks, which I want to use in multiple views. Something like:
base.scala.html
#()
#display(product: Product) = {
#product.name ($#product.price)
}
products.scala.html
...
#display(product)
...
How can I import such file in view to use #display block?
Each view fragment should be in it's own file, with it's own parameters declared there. A Play template is supposed to work like a single function, not many. Instead, create a directory called base, and separate the view fragments into separate files.
views/base/display.scala.html
#(product: Product)
#product.name ($#product.price)
views/products.scala.html
...
#base.display(product)
...
Put it in a separate file, display.scala.html and make it the only/actual template, the file name is the fragment/function name:
#(product: Product)
#product.name ($#product.price)
if in the same package just call it
#display(product)
or if in another package either use full package name or import it first
#some.package.display(product)
#import some.package.display
#display(product)
Take a look into templating doc, section: Tags (they are just functions right?)
In general you can i.e. move your block to views/tags/displayProduct.scala.html (and use it as common template) so you can use it in ANY view with:
<div class="product">
#tags.displayProduct(product)
</div>

Parameter and view naming collisions in Play/Scala templates

I am new to Play Framework and still trying to wrap my head around some things with the new Scala template engine.
Let's say I have the following package structure:
app/
app/controllers/Items.scala
app/models/Item.scala
app/views/layouts/page.scala.html
app/views/item/show.scala.html
app/views/item/details.scala.html //partial
And this is my item/show template:
#(item: Item, form: Form[Item])(implicit flash: Flash)
#layout.page() {
#*want to include details partial, wont work due to item param*#
#item.details(item)
}
Since including another template (e.g. including item/details above) is the exact same syntax as accessing a template parameter (e.g. item above), obviously this existing naming convention won't work without something changing.
I know I can rename my "app.views.item" package to "app.views.items", and rely on singular/plural forms to differentiate the view from the param name, but this does not seem like a very straightforward solution. Also what if I really want the parameter name to be the same as the view package?
One idea I have is to prepend all my views with an extra top level package:
app/views/views/item/details.scala.html
So the include syntax would be #views.item.details(), but again this is obviously a hack.
What is a good way to avoid this issue? How can I better organize my code to avoid such naming collisions?
Most other template engines use operations like "include" or "render" to specify a partial include. I don't mean to offend anyone here, but is the Play Scala template engine syntax so terse that it actually dictates the organization of code?
3 solutions:
First
Typpicaly for partial templates you should use tags as described in the docs, where app/views/tags folder is a base:
file: app/views/tags/product.scala.html
in the templates (no initial import required in the parent view full syntax will allow you to avoid name-clash: #tags.packageName.tagName()):
<div id="container">
#tags.product(item)
</div>
Of course in your case you can also use packages in the base folder
file: app/views/tags/item/product.scala.html
<div id="container">
#tags.item.product(item)
</div>
I'm pretty sure that'll solve your problem.
Second
To avoid clash without changing package's name you can just rename the item in your view, also I recommend do not use a form name for the Form[T] as it can conflict with helpers:
#(existingItem: Item, existingItemForm: Form[Item])(implicit flash: Flash)
#layout.page() {
#item.details(existingItem)
}
Third
If you'll fill your Form[Item] before passing to the view with given Item object, you don't need to pass both, as most probably you can get data from the form:
#(itemForm: Form[Item])(implicit flash: Flash)
#layout.page() {
<div>Name of item is: #itemForm("name").value (this is a replacemnet for ##existingItem.name </div>
#item.details(itemForm)
}
Of course in you product.scala.html you'll need to change the #(item: Item) param to #(itemForm: Form[Item])