Coder Social home page Coder Social logo

angular-custom-elements's Introduction

angular-custom-elements

Build Status

Angular 1.x directive to hold all yr Custom Element bindings together ๐Ÿ˜

note: This is still experimental so use at your own risk

Install

npm install --save angular-custom-elements

Usage

  • Include the dist/ce-bind.(min).js script in your page.
  • Add robdodson.ce-bind as a module dependency to your app.
  • For interpolated/two-way bindings: Add the ce-interpolated directive to any Custom Element or Polymer Element to keep your interpolated bindings in sync.
<div ng-controller="MainCtrl as main">
  {{main.greeting}}
  <fancy-input message="{{main.greeting}}" ce-interpolated></fancy-input>
</div>
  • For one-way bindings: Add the ce-one-way directive to any Custom Element or Polymer Element, to keep its one-way bindings in sync.
app.component('fooComponent', {
 template: `
   <p>Angular string is: {{$ctrl.str}}</p>
   <my-input message="$ctrl.str"
             on-message-changed="$ctrl.onMessageChanged($event)"
             ce-one-way>
   </my-input>
  `

How does it work?

Interpolated bindings

Polymer's two-way binding system is event based. Anytime a bindable property changes it fires an event named: [property]-changed. For example, a two-way bindable property named foo would fire a foo-changed event.

This means we can listen for the *-changed events coming off of an element, and take the new value and pass it into our scope using $evalAsync.

This also means you could write your own Custom Elements that didn't use Polymer and so long as they fired a [property]-changed event, and the event.detail.value contained the new value, it would also work.

One-way bindings

For Angular 1.5 style one-way bindings, we look at the Input, e.g. friend="$ctrl.person", set the property on the Custom Element using the value from $ctrl.person, and create a watcher to update the Custom Element anytime the $ctrl.person property changes.

For Outputs, we look for any attribute starting with on- and create an event listener which triggers the corresponding handler in our Angular controller. E.g. on-person-changed="$ctrl.updatePerson($event)" will listen for the person-changed event and call the controller's updatePerson method, passing the event object to it. The controller can then take the value of event.detail and choose what to do with it. Because Custom Elements typically communicate to the outside world using Events, this binding will only create event listeners. This means you cannot use the Angular 1.5 approach of creating a callback with named arguments:

// This will NOT work. The argument will be ignored and the handler
// will always be called with the event object
on-person-changed="$ctrl.updatePerson({name: 'Bob'})"

Instead, treat these as regular event listeners and use the value(s) passed via event.detail.

How is this different from other Polymer + Angular adapters?

The two adapters I've found are angular-bind-polymer and ng-polymer-elements. Both are very cool but they have limitations which this project (hopefully) fixes.

angular-bind-polymer relies on Mutation Observers to notify the scope when an element's attributes change. This only works if the element chooses to serialize its internal state back to strings and reflect them to attributes. Most Polymer elements do not do this, meaning they can't be used with angular-bind-polymer.

ng-polymer-elements attempts to create directives for specific attributes exposed by Polymer elements but this becomes a bit of an arms race as every time an element creates a new attribute/property then ng-polymer-elements needs to be updated. It also relies on Object.observe which has been removed from the platform, so an additional polyfill is required.

angular-custom-elements's People

Contributors

bgotink avatar robdodson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

angular-custom-elements's Issues

Multiple elements in the same scope

If you're using multiple instances of the same element on a page, and within the same controller, updating an attribute on one element should not affect any of the others

Commonjs support

How about making this importable as an es6/commonjs module, so we can bring it in using npm or jspm?

Angular bindings misunderstanding.

I have gone over some of the tests, and there is an issue.
Most of the things in there are not supposed to work as they do now.

 <my-input message="{{main.greeting}}" ce-interpolated></my-input>

link

Is making a 2 way binding (updating the angular side of things) out of something that is designed to be a 1 way (angular --> DOM) binding.

This is a really cool solution, but it is going against the way angular normally works.

2 way bindings are centered around ngModel. The controller that comes along with it makes it possible to efficiently create an interface with all 3rth parties. Also it makes it more explicit what's happening.

The line should read something like:

<my-input ng-model="main.greeting" bind-to-attr="message"></my-input>

There is no "magic" and its very explicit how it is supposed to work.
here I created a first draft for this concept.
where you can see this in action.

It is not a perfect solution. It's very hard to make a solution that works in every case, because there are missing pieces. One piece that is missing for example is a way to tell an custom element to render the new data to its view. Polymer has this part covered, but I don't know if all of polymer elements follow this convention.

Test ng-if

Apparently ng-if leaves elements in the DOM but just visibly hides them. This means that they may have their bindings fulfilled and may do weird stuff. Need to verify if the bindings fulfill correctly and if it causes any issues

bind-value-to with custom elements v.1

Hey Guys, I am using AngularJS v.1.6.6 with a UI Widget kit called XEL (using custom elements v.1):

https://xel-toolkit.org/

The XEL widget toolkit is very cool and absolutely perfect for the electron based application I am working on (to be honest: the most promising and coolest I have found). For some reasons, I can not move to Angular 2 or above. Unfortunately the very skilled developer of the xel-toolkit has absolutely no AngularJS knowledge. On my side, I am more a designer than a coder, so I have no deep knowledge of Angular JS so that I could help the developer.

So I was hoping that your angular-custom-elements would solve my dilemma of using custom elements with AngularJS 1. Some of the XEL elements are working fine with AngJS, but some are not. For example (code compared with regular HTML elements, so that I am sure that the functions itself are OK):

Working:
<input type="checkbox" ng-true-value="right" ng-false-value="right" bind-value-to="originX">
Not working:
<x-checkbox ng-true-value="right" bind-value-to="originX" ce-interpolated></x-checkbox>
OR

Working:
<input type="radio" name="origin-x" value="right" bind-value-to="originX">
Not working:
<x-radio value="right" bind-value-to="originX" ce-interpolated></x-radio>

Most of the other components are working fine (even the complex ones like ) but this two important controls are simply not working. With or without angular-custom-elements...

I know that this is more a StackOverflow type of question, so sorry for this... But help is HIGHLY appreciated....

Polymer throws warning "Unable to parse JSON"

Custom Elements upgrade the moment they're inserted and parsed. This means one of two things can happen depending on the kind of binding being used:

Interpolated Binding

// Assume baz=[1,2,3]
<x-foo bar="{{baz}}">
  1. Initially the element will see "{{baz}}" as the value for bar.
  2. Angular will fulfill the binding, transforming it into `

If the element is expecting an Array, Polymer will throw a warning because it initially tried to call JSON.parse("{{baz}}"), before Angular fulfilled the binding

Angular 1.5 Input style

// Assume baz=[1,2,3]
<x-foo bar="$ctrl.baz">
  1. Angular will leave the $ctrl.baz syntax in the DOM forever
  2. If you're using the ce-one-way it will set the property bar=[1,2,3]. Note that we're setting a property binding here, not doing string interpolation in the attribute

Similar to above, the element will initially call JSON.parse("$ctrl.baz"), the JSON parse will fail and it'll throw a warning, and then the directive will kick in and fulfill the value.


Another thing to note is how Polymer's handling the JSON.parse. https://github.com/Polymer/polymer/blob/master/src/micro/attributes.html#L199-L214
Note line 211 which sets value=null. THIS WILL CAUSE OBSERVERS TO RUN. Even though the value is null, observers run for any value change (except if the value is undefined). Polymer should set this value back to undefined. Issue filed @ Polymer/polymer#3860

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.