Best strategy for Angular Front-End Form Building by Users [closed] - node.js

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 3 years ago.
Improve this question
Good day, whoever reads this, thanks for taking the time to possibly assist!
Back in the day, I used to work a lot with Wordpress (PHP) and there was this plugin we used to gather metadata: Advanced Custom Fields (advancedcustomfields . com). What made it cool was that you could visually set up groups of questions (a form if you will), by selecting the types of questions and configure their setup and style (input with label in inside or outside, or, table with rows and columns specifying each key alongside which the answer would be saved against in the database).
I'm looking to build the exact same thing in Angular 8+, allowing my client to choose whatever type of field (input) they want and group them together. How do you suggest I go about this:
1) build custom components like: text input/area, radio, table, map, image, file upload, checkboxes, date/time pickers, select boxes, groups etc (each carrying conditional rules to show or not depending on some other component)... and then let the user choose the relevant parameters for each component and send them to the component ngOnInit() with #Input or a service?
2) does a similar package already exist for me to leverage such functionality quicker?
Appreciate the advice and input :)
Rgds,
Wzz

Have a look at ngx-formly. Another option is ng-dynamic-forms. These libraries have dynamically configurable input elements section.
ngx-formly code sample from their demo below:
app.component.ts
import { Component } from '#angular/core';
import {FormGroup} from '#angular/forms';
import {FormlyFieldConfig} from '#ngx-formly/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
})
export class AppComponent {
form = new FormGroup({});
model = {};
fields: FormlyFieldConfig[] = [
{
key: 'input',
type: 'input',
templateOptions: {
label: 'Input',
placeholder: 'Input placeholder',
required: true,
}
},
{
key: 'textarea',
type: 'textarea',
templateOptions: {
label: 'Textarea',
placeholder: 'Textarea placeholder',
required: true,
}
},
{
key: 'checkbox',
type: 'checkbox',
templateOptions: {
label: 'Checkbox',
}
},
{
key: 'select',
type: 'select',
templateOptions: {
label: 'Select',
placeholder: 'Select placeholder',
required: true,
options: [
{ label: 'Option 1', value: '1' },
{ label: 'Option 2', value: '2' },
{ label: 'Option 3', value: '3' },
]
}
},
{
key: 'radio',
type: 'radio',
templateOptions: {
label: 'Radio',
required: true,
options: [
{ label: 'Option 1', value: '1' },
{ label: 'Option 2', value: '2' },
]
}
}
];
onSubmit() {
if (this.form.valid) {
alert(JSON.stringify(this.model, null, 2));
}
}
}
app.component.html
<div class="header">
<img src="https://raw.githubusercontent.com/ngx-formly/ngx-formly/v5/logo.svg?sanitize=true" alt="" width="72" height="72">
<h4 class="mat-h2">Angular Formly Material</h4>
</div>
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<formly-form
[form]="form"
[model]="model"
[fields]="fields">
</formly-form>
<button type="submit" color="primary" mat-raised-button>
Submit
</button>
<button type="reset" color="warn" mat-raised-button>
Reset
</button>
</form>

Related

How do I format [future, non-current] dates in Eleventy + Nunjucks?

I'm building a site with a CMS (Netlify) for a local band, and they have future gig dates they will put on the site. So far the dates show up as very long non-formatted strings that include the time and time zone. I'm trying to figure out how to format the dates to be simpler (day, date, time for example).
I've tried plugins like nunjucks-date but I'm a little confused about how to use a plugin (and filters) in this case.
My repo: https://github.com/mollycarroll/serapis-eleventy-2
Example gig entry:
---
layout: gig
venue: Cedar Lake Cellars
date: 2022-05-28
time: 6pm
city: Wright City, MO
---
Gig template:
<h2>{{ venue }}</h2>
<h4>{{ city }} {{ date }} {{ time }}</h4>
config.yml for the CMS:
- name: 'gigs'
label: 'Shows'
folder: 'src/gigs'
create: true
slug: '{{month}}-{{day}}-{{venue}}'
fields:
- { label: 'Layout', name: 'layout', widget: 'hidden', default: '_includes/gig.njk' }
- { label: 'Date', name: 'date', widget: 'date', default: '' }
- { label: 'Time', name: 'time', widget: 'string', default: '' }
- { label: 'Venue', name: 'venue', widget: 'string', default: '' }
- { label: 'City', name: 'city', widget: 'string', default: '' }
Thanks for any help.
First, you should create a filter, let's say src/filters/date.js with the following content:
const { DateTime } = require("luxon");
// Add a friendly date filter to nunjucks.
// Defaults to format of LLLL d, y unless an
// alternate is passed as a parameter.
// {{ date | friendlyDate('OPTIONAL FORMAT STRING') }}
// List of supported tokens: https://moment.github.io/luxon/docs/manual/formatting.html#table-of-tokens
module.exports = (dateObj, format = 'LLLL d, y') => {
return DateTime.fromISO(dateObj, { zone: "Europe/Amsterdam", locale: "en" }).toFormat(format);
};
Make sure you check Luxon documentation for details. Then add the filter in .eleventy.js:
module.exports = function(eleventyConfig) {
...
eleventyConfig.addFilter("date", require("./src/filters/date.js"));
...
};
Now you can use it in Nunjacks with a default value {{ date }}, in this example 'LLLL d, y', or any value you need at a certain position on your website {{ date | date('dd. LLLL yyyy.') }}. This can be very useful if you need at some point just month and year or just day and month.
You can even create multiple language filters, like dateEn.js and dateDe.js, and format each to its own language if you have a multilingual site.
Hope this helps.
EDIT: In order for this filter to work the dateObj should be in ISO 8601 format.

Why doesn't the image from the external link work in gatsby?

Excuse me, please, I am just learning. In some gatsby templates I can insert as Image - an image from a URL and in some templates Image don't want to display it.
What does it depend on and how to edit the code to make the url work? (My knowledge about graphql is rather basic)
this is the code for the blog template:
/** #jsx jsx */
import { jsx } from 'theme-ui'
import { Link, graphql } from "gatsby"
import Img from "gatsby-image"
import { RiArrowRightLine, RiArrowLeftLine } from "react-icons/ri"
import Layout from "../components/layout"
import SEO from '../components/seo';
const styles = {
'article blockquote': {
'background-color': 'cardBg'
},
pagination: {
'a': {
color: 'muted',
'&.is-active': {
color: 'text'
},
'&:hover': {
color: 'text'
}
}
}
}
const Pagination = (props) => (
<div
className="pagination -post"
sx={styles.pagination}
>
<ul>
{(props.previous && props.previous.frontmatter.template === 'blog-post') && (
<li>
<Link to={props.previous.frontmatter.slug} rel="prev">
<p
sx={{
color: 'muted'
}}
>
<span className="icon -left"><RiArrowLeftLine/></span> Previous</p>
<span className="page-title">{props.previous.frontmatter.title}</span>
</Link>
</li>
)}
{(props.next && props.next.frontmatter.template === 'blog-post') && (
<li>
<Link to={props.next.frontmatter.slug} rel="next">
<p
sx={{
color: 'muted'
}}
>Next <span className="icon -right"><RiArrowRightLine/></span></p>
<span className="page-title">{props.next.frontmatter.title}</span>
</Link>
</li>
)}
</ul>
</div>
)
const Post = ({ data, pageContext }) => {
const { markdownRemark } = data // data.markdownRemark holds your post data
const { frontmatter, html, excerpt } = markdownRemark
const Image = frontmatter.featuredImage ? frontmatter.featuredImage.childImageSharp.fluid : ""
const { previous, next } = pageContext
let props = {
previous,
next
}
return (
<Layout className="page">
<SEO
title={frontmatter.title}
description={frontmatter.description ? frontmatter.description : excerpt}
image={Image}
article={true}
/>
<article className="blog-post">
<header className="featured-banner">
<section className="article-header">
<h1>{frontmatter.title}</h1>
<time>{frontmatter.date}</time>
</section>
{Image ? (
<Img
fluid={Image}
objectFit="cover"
objectPosition="50% 50%"
alt={frontmatter.title + ' - Featured image'}
className="featured-image"
/>
) : ""}
</header>
<div
className="blog-post-content"
dangerouslySetInnerHTML={{ __html: html }}
/>
</article>
{(previous || next) && (
<Pagination {...props} />
)}
</Layout>
)
}
export default Post
export const pageQuery = graphql`
query BlogPostQuery($id: String!) {
markdownRemark(
id: { eq: $id }
) {
id
html
excerpt(pruneLength: 148)
frontmatter {
date(formatString: "MMMM DD, YYYY")
slug
title
description
featuredImage {
childImageSharp {
fluid(maxWidth: 1980, maxHeight: 768, quality: 80, srcSetBreakpoints: [350, 700, 1050, 1400]) {
...GatsbyImageSharpFluid
...GatsbyImageSharpFluidLimitPresentationSize
}
sizes {
src
}
}
}
}
}
}
`
typical post:
---
template: blog-post
title: my title
slug: /plant/bud
date: 2020-05-13 12:37
description: abc
featuredImage: /assets/screen-post-hixmjdah9xhoo-unsplash.jpg (but online image from imgurl png doesnt work)
---
post nr 1
edited ///
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/static/assets/`,
name: `assets`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/src/content/`,
name: `content`,
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-transformer-remark`,
options: {
gfm: true,
plugins: [
netlifyCmsPaths,
`gatsby-remark-reading-time`,
{
resolve: `gatsby-remark-images`,
options: {
maxWidth: 1024,
showCaptions: true,
linkImagesToOriginal: false,
tracedSVG: true,
loading: "lazy",
},
},
`gatsby-remark-responsive-iframe`,
{
resolve: `gatsby-remark-prismjs`,
options: {
classPrefix: "language-",
inlineCodeMarker: null,
aliases: {},
showLineNumbers: false,
noInlineHighlight: false,
// By default the HTML entities <>&'" are escaped.
// Add additional HTML escapes by providing a mapping
// of HTML entities and their escape value IE: { '}': '{' }
escapeEntities: {},
},
},
],
},
},
In Gatsby, you can insert images from external sources using the standard HTML <img> tag with the src property:
<img src="https://via.placeholder.com/150" alt="Alt text" width="500" height="600">
If you want to keep the benefits of gatsby-image across the external (or online) images, you should need to use some dependencies to achieve lazy loading and other features.
However, to use gatsby-image you need to allow Gatsby and the inferred GraphQL schema to use their transformers (gatsby-transformer-sharp and sharps (gatsby-plugin-sharp) across with the filesystem (gatsby-source-filesystem) or in other words, Gatsby needs to have access to the images that needs to parse to create a valid queryable GraphQL schema, that will be consumed with the gatsby-image.
In addition, you need to specify the folder of your project where those images belong (setting the filesystem):
const path = require(`path`)
module.exports = {
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: path.join(__dirname, `src`, `images`),
},
},
`gatsby-plugin-sharp`,
`gatsby-transformer-sharp`,
],
}
Once the filesystem is set and the images are processed, a GraphQL node is created, and you are allowed to use the fragments like the one you've provided:
featuredImage {
childImageSharp {
fluid(maxWidth: 1980, maxHeight: 768, quality: 80, srcSetBreakpoints: [350, 700, 1050, 1400]) {
...GatsbyImageSharpFluid
...GatsbyImageSharpFluidLimitPresentationSize
}
sizes {
src
}
}
}
Since the external images can't be directly processed by Gatsby, they can't be used with gatsby-image. Depending on the source of those images, some plugins allow you to keep using gatsby-image from external sources (usually from CMSs like Contentful and others).
You can check for further documentation in Working with images docs.
Update (01/06/2021)
In the last Gatsby version (v2.30) they've added a new experimental feature, still in beta to support external images in a <StaticImage> component. To enable it, just upgrade to the latest Gatsby version (via npm or yarn) and add the following flags in your running scripts:
GATSBY_EXPERIMENTAL_REMOTE_IMAGES=1 gatsby develop
GATSBY_EXPERIMENTAL_REMOTE_IMAGES=1 gatsby build
You can then pass absolute URLs to StaticImage:
<StaticImage src="https://placekitten.com/400/400" alt="Kittin" />

Adding Dropdowns in a vue.js router-link

I have created a vue.js router and inserting the links found in an array using the structure found hereafter. This displays the links horizontally. However, I would like to insert dropdowns, instead of simple links. Can this be done using this or similar structure somehow?
<nav style="text-align: right">
<router-link class="spacing" v-for="routes in links"
v-bind:key="routes.id"
:to="`${routes.page}`">{{routes.text}}</router-link>
</nav>
links: [
{
id: 0,
text: 'Buy',
page: '/Buy'
},
{
id: 1,
text: 'Sale',
page: '/Sale'
},
{
id: 2,
text: 'Transactions',
page: '/Transactions'
},
{
id: 3,
text: 'Help',
page: '/Help'
}
]
Yeah, there are a few ways you could do that, though you'll have to loop over something different than the <router-link>, since that component renders an <a> tag.
I would first adjust your HTML to allow for the drop-down interaction you want, whether it's hover- or click-based, then change your data structure and loop to support it.
I might do something like this:
<nav style="text-align: right">
<div
class="nav-item"
v-for="link in links" // Move loop to container of shown link and it's dropdown markup
>
<router-link
:key="link.id"
:to="`${link.page}`"
>
{{ link.text }}
</router-link>
<div class="nav-item-drawer">
<router-link
v-for="subLink in link.subLinks"
:key="subLink.id"
:to="`${subLink.page}`"
>
{{ subLink.text }}
</router-link>
</div>
</div>
</nav>
with the following data structure:
links: [
{
id: 0,
text: 'Buy',
page: '/Buy',
subLinks: [
{
id: 0,
text: 'Buy Sublink 1',
page: '/Buy-more'
},
{
id: 1,
text: 'Buy Sublink 2',
page: '/Buy-less'
},
]
},
{
id: 1,
text: 'Sale',
page: '/Sale'
},
//...
]

Building dynamic HighCharts and image Highcharts with (mostly) one codebase?

We're already creating dynamic HighCharts for our webpages--these have a few javascript dependencies and a chart-generation script. We'd like to start creating PDFs of these charts using the new HighCharts/Node/PhantomJS suite HighCharts has rigged up (see press release). Our image-gen node server would run on a separate box/vm. How can we do this without having to maintain two separate codebases for the same chart? I'm not too familiar with Node yet, so I'm not sure how requesting the scripts with a web request would work. I'm guessing a lot of HighCharts users that want to start generating some of their charts as images server-side will run into a similar issue with managing two related codesets...
In essence, we already have have this:
Webserver -> JSON (data) + foo.js + bar.js + foo.html -> webpage with dynamic charts.
We'd like to build:
Web-server -> JSON (data) + separate Node Server + foo.js + bar.js -> images available via web request
Obviously some redundancy. How can we manage the dependencies?
While node is awesome, I felt that approach was needlessly complex, with having to many moving parts that could break. So I did the super simple solution of creating files dynamically. The only problem i faced was deleting the temporary file after adding it to the pdf. It would break the PDF from rendering. And setting the directory to /tmp, crashed phantomjs. The best idea i came up with currently is putting the tempory generated files, in a temp directory, then deleting everything in that directory every night, with a cronjob.
I post this out of code simplicity. It should be in a function, to maintain code re-usability.
<?php
$TmpInFileName = 'tmp/graph_'.md5($CurrentDate.rand(666,9482845713)).'.js';
$TmpGraphFileName = 'tmp/pnggraph_'.md5($CurrentDate.rand(2666,54713)).'.png';
$Data = "
{
chart: {
zoomType: 'xy',
width: 700,
height: 520
},
credits: {
enabled: false
},
colors: [
'#2f7ed8',
'#910000',
'#8bbc21',
'#1aadce',
'#492970',
'#f28f43',
'#77a1e5',
'#c42525',
'#a6c96a'
],
title: {
text: 'Sample Graph - created at ".date('m/d/Y g:i:s a')."',
style: {
fontSize: '16px',
}
},
xAxis: [{
categories: ['00:00', '00:15', '00:30', '00:45', '01:00', '01:15', '01:30']
}],
yAxis: [{
labels: {
format: '{value}',
style: {
fontSize: '14px',
color: Highcharts.getOptions().colors[1]
}
},
title: {
text: 'Y axis',
style: {
fontSize: '16px',
color: Highcharts.getOptions().colors[1]
}
}
}, { // Secondary yAxis
title: {
text: 'Sec Yaxis',
style: {
fontSize: '16px',
color: Highcharts.getOptions().colors[0]
}
},
labels: {
format: '{value}',
style: {
fontSize: '14px',
color: Highcharts.getOptions().colors[0]
}
},
opposite: true
}],
tooltip: {
shared: true
},
legend: {
layout: 'horizontal',
backgroundColor: (Highcharts.theme && Highcharts.theme.legendBackgroundColor) || '#FFFFFF'
},
series: [{
name: 'first',
type: 'spline',
yAxis: 1,
data: [0, -119.9502311075212, -119.96203992145706, -119.98172620218355, -119.71898290168028, -119.97023935590325, -119.95230287195413]
},
{
name: 'second',
type: 'spline',
yAxis: 1,
data: [0, -119.24222667756482, -119.60905809195222, -119.63522965403729, -119.11011466187935, -119.63643171374981, -119.54969080301575]
},{
name: 'third',
type: 'column',
data: [10, 11, 9, 7, 5, 2, 7]
},{
name: 'fourth',
type: 'column',
data: [0, -0.7080044299563895, -0.35298182950484147, -0.34649654814626274, -0.6088682398009269, -0.33380764215343106, -0.40261206893838164]
}]
}";
try {
$myfile = fopen($TmpInFileName, "w") or die("Unable to open file!");
fwrite($myfile, $Data);
fclose($myfile);
} catch (Exception $e) {
echo 'Error: '.$e.' <br />';
}
$URL_Command = "phantomjs /highcharts/exporting-server/phantomjs/highcharts-convert.js -infile $TmpInFileName -outfile $TmpGraphFileName -width 600";
exec($URL_Command);
echo '<img src="'.$TmpGraphFileName.'" alt="Could not load img: '.$TmpGraphFileName.'">';
?>
I hope this helps. I couldn't find a good solution that didn't involve Node.JS or Java to do this. I wanted a pure PHP solution.
We decided to pass the entire highcharts config object (e.g. Highcharts.chart(configObj)) to the node server as a URL-encoded string. We had to put a few rendering functions over on the node server, but it wasn't too bad. We also stuck some of the rendering functions in the string config object. Not the most beautiful result, but it worked.

Sencha - Add custom attributes to element

I want my div to look like this
<div id="example" customAtt="try"></div>
How can I add custom attribute to panel,button etc. in sencha?
thank you
If it's a Ext.Component, you can do the following
listeners: {
afterrender: function (component) {
component.getEl().dom.setAttribute("myCustomAttribute", "SOME_VALUE");
}
}
You can use autoEl in classic framework:
Ext.create({
xtype: 'component',
renderTo: Ext.getBody(),
html: 'Hi !!!',
id: "example",
autoEl: {
customAtt: "try"
}
});
Crate ...
<div class="x-component x-component-default x-border-box" customatt="try" id="example">Hi !!!</div>
You can easily add custom attributes, the same way you define config attributes.
mycont = {
xtype: 'container',
id: 'cont123',
width: 300,
height: 100,
customAttribute1: customAttribute1Value
customAttribute2: customAttribute2Value
...
}

Resources