Code Monkey home page Code Monkey logo

factor's People

Contributors

mwardle avatar wardlem avatar

Watchers

 avatar  avatar

factor's Issues

Dynamic tag names for elements in templates

Factor should support dynamic tag names in template elements. A special templating syntax needs to be added to tag names for this. Because of the limited set of allowed characters in tag names, the most likely candidate for doing this is a : prefix.

define('MyElement', {
  props: {
    childTag: {
      type: String,
      default: 'div'
    }
  },
  template: '<:childTag></:childTag>'
})

Perhaps more in-line with tag and attribute directives would be to allow attribute prefix directives to be defined.

As yet another alternative, a new built-in tag directive could be defined:

define('MyElement', {
  props: {
    childTag: {
      type: String,
      default: 'div'
    }
  },
  template: '<dynamic tag="childTag"></dynamic>'
})

This may be the best option since it does not require any updates to the parser, which could potentially add overhead to the parsing process.

Opt-out of rendering system (Imperative components)

Some components do not require Factor's rendering system. The define function should expose a reactive option that turns the rendering system off for the component when set to false. The option should default to true. When the rendering system is off and a template is supplied, the template HTML will be still be inserted into the component's root (usually shadow root) node as a one-time action.

URL stylesheets

Stylesheets should be able to point to a remote resource. If a stylesheet looks like a URL or path (which is not valid CSS, so there should not be a conflict), or if a stylesheet is an instance of URL, the stylesheet should be loaded from a remote resource.

Event helpers options

The eventToTransform and eventToAction helpers need options to automatically stopPropagation and preventDefault.

Tag directives do not work in tables

Because of the way that HTML is parsed by the browser, tag directives do not work in tables because the tag is not valid inside a table. An alternative to tag directives is needed, such as declaring a directive as an attribute.

// This doesn't work
<table>
  <tbody>
    <for items="rows" as="row">
      <tr><td>{{row.name}}</td></tr>
    </for>
  </tbody>
</table>
// This would work
<table>
  <tbody>
    <tr directive="for" items="rows" as="row">
      <td>{{row.name}}</td>
    </tr>
  </tbody>
</table>

Enumerated Property Type

Sometimes there is a limited set of permissable values for a property. There should be a property type to handle these situations.

Need a mechanism for easily passing data to components in html

It is currently difficult to send data to top-level components. For example, to set the items in a theoretical list component, one would have to do something like this:

<my-list></my-list>
<script>
  const myList = document.querySelector('my-list')
  myList.items = [
    // Long list of items
  ]
</script>

An attribute combined with an Object prop can be used, but it becomes unwieldy for large objects since spaces are not allowed in the attribute value.

A more convenient way of doing this would be something like this:

<my-list>
  <script prop="items" type="application/json">
    [
      // Long list of items as json
    ]
  </script>
</my-list>

A script element was chosen for the above example, because it is not rendered or parsed by the engine if it has a non-javascript type. The disadvantage of using a script is that it cannot pass in javascript code.

Multiple stylesheets

Multiple stylesheets should be allowed for an element. Additionally, they should be loadable from a remote resource. Furthermore, they should be able to be turned off and on.

const MyElement = define('MyElement', {
  props: {
    color: { type: String },
    text: { type: String }
   },
  styles: [
    new URL('/some/remote/styles.css'),
    'p {font-weight: bold}',
    {
       content: 'p {color: blue}',
       condition: ({color}) => color === 'blue' 
    }
  ],
  template: '<p>{{text}}</p>'
})

Change the prop tag directive prefix, add id tag directive

Instead of using # for props, use it for an id attribute directive. Use just : for props. Since . is used for the class directive (taken from CSS), # should also be used for the id directive.

The primary reason an id directive has not yet been added is that the id name hasn't really made sense. However, it might make sense as a prefix.

const template = `<div #item="itemNumber"></div>`
// the id will be set to something to `item-12` if itemNumber resolves to 12

Having no id name will just return the value. An array id will be joined with the - character.

The property syntax will now look like:

const template = `<div :someProp="valueKey"></div>`

Mixins

Components should be composable with mixins.

import InputMixin from '../mixins/InputMixin'
const TextInput = define('TextInput', {
  mixins: [InputMixin({type: 'text'})]
})

An open question is how templates should be handled when it comes to mixins. The easiest solution is to make templates non-inheritable through mixins. Another simple solution would be to inherit the last template in the mixin list. A more complex solution would be to allow templates to be composed in some way through a templating syntax or template pre-processor. The last solution seems to violate the principle of YAGNI. The second solution seems the most reasonable, since it can be easily overwritten by manually setting the template in the define options.

Add a static `toString()` method for components that returns the tag name.

It would often be more convenient to use the element name directly in your template rather than using the tag name. Because of the way Factor's views are parsed and rendered, this isn't really feasible. As a compromise, being able to use the type in your template would using template literals would be nice. This can already be done by referencing the MyElement.type variable:

import OtherElement from './OtherElement.mjs'

const MyElement = define('MyElement', {
  template: `<${OtherElement.tag}></${OtherElement.tag}>`
})

This proposal would allow you to drop the .tag:

import OtherElement from './OtherElement.mjs'

const MyElement = define('MyElement', {
  template: `<${OtherElement}></${OtherElement}>`
})

You can still access the default behavior by using Function.prototype.toString.call(MyElement) if it is ever needed.

Stylesheets

Custom elements should use shared stylesheets. Where constructable stylesheets are available, they should be used. Otherwise, they should be mimicked as efficiently as possible.

FOUC

There is a flash of unstyled content when an element loads. The element should not render until the styles are fully loaded.

Attributes are stripped out of tables

Non-standard attributes are stripped out of tables. This makes the directive attribute unreadable when the template is processed. There may be other elements for which this is true as well.

This problem requires a big fix. It would feel weird to have a special rule just for times like these, so we can't do that. Instead, all tag directive attributes (including there parameters) need to be prefixed. While we do this, we should also prefix the directive tags.

<tr f:directive="for" f:values="items" f:as="item" #item="index"><td>{{item.name}}</td></tr>

Preliminary testing shows that prefixed attributes (any attribute containing a symbol character) are not stripped from an element when it is parsed by the browser.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.