Skip to content

Instantly share code, notes, and snippets.

@Mischi
Last active August 25, 2016 20:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Mischi/fca8647565c9ed27dae750d69a48c618 to your computer and use it in GitHub Desktop.
Save Mischi/fca8647565c9ed27dae750d69a48c618 to your computer and use it in GitHub Desktop.
attach a directive's controller onto the scope like ng's form[name] does!
<!DOCTYPE html>
<html lang="en">
<head>
<title>ng-attach poc</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body ng-app="ng-attach-poc">
<ngap-parent></ngap-parent>
<script src="https://npmcdn.com/angular@latest/angular.js"></script>
<script>
'use strict';
const app = angular.module('ng-attach-poc', [])
app.component('ngapParent', {
controller: function ParentController() {},
controllerAs: 'parent',
template: `
<h1>{{parent.child.message}}</h1>
<ngap-child ng-attach="parent.child"></ngap-child>
`
});
app.component('ngapChild', {
controller: function ChildController() {
this.message = 'Hello World';
},
controllerAs: 'child',
template: `
<h2>{{child.message}}</h2>
<input type="text" ng-model="child.message">
`
});
app.directive('ngAttach', function ($parse) {
// copied from https://github.com/angular/angular.js/blob/e1da4bed8e291003d485a8ad346ab80bed8ae2e3/src/jqLite.js#L139
const SPECIAL_CHARS_REGEXP = /([:\-_]+(.))/g;
const MOZ_HACK_REGEXP = /^moz([A-Z])/;
function camelCase(name) {
return name.replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
return offset ? letter.toUpperCase() : letter;
}).
replace(MOZ_HACK_REGEXP, 'Moz$1');
}
// copied from https://github.com/angular/angular.js/blob/master/src/ng/directive/form.js#L540
function getSetter(expression) {
if (expression === '') {
//create an assignable expression, so forms with an empty name can be renamed later
return $parse('this[""]').assign;
}
return $parse(expression).assign || noop;
}
return {
compile: function ngAttachCompile() {
let ngAttach = '';
return {
pre: function ngAttachPreLink(scope, element, attr) {
ngAttach = attr.ngAttach;
const setter = getSetter(ngAttach);
const directiveName = attr.ngAttachDirective || element[0].tagName.toLowerCase();
const controller = element.controller(camelCase(directiveName));
setter(scope, controller);
attr.$observe('ngAttach', function(newValue) {
if (ngAttach === newValue) return;
ngAttach = newValue;
setter(scope, undefined);
setter = getSetter(ngAttach);
setter(scope, controller);
});
}
}
},
restrict: 'A',
scope: false
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment