Skip to content

Instantly share code, notes, and snippets.

@mbret
Last active March 29, 2018 14:27
Show Gist options
  • Save mbret/a53127facc86b8aa0a9fabf98d149507 to your computer and use it in GitHub Desktop.
Save mbret/a53127facc86b8aa0a9fabf98d149507 to your computer and use it in GitHub Desktop.
Angularjs one way binding
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.js"></script>
<style type="text/css">
</style>
<title>Angular: true one way binding</title>
</head>
<body>
<div ng-app="demo">
<app></app>
</div>
<script type="text/javascript">
class App {
static get declaration () {
return {
selector: 'app',
binding: {},
template: App.template,
controller: App
};
}
static get $inject () {
return ['owService'];
}
constructor ({onChange}) {
this.state = {
firstName: ''
};
this.handleChange = onChange(field => {
const {$name, $modelValue, $error} = field;
this.state[$name] = $modelValue;
});
this.handleSecondChange = onChange(field => {
this.state.firstName = field.$modelValue;
});
}
static get template () {
return `
<p>App.state.firstName: {{$ctrl.state.firstName}}</p>
<form name="form">
<label>This input is bound to a dummy ngModel so it will never mutate your state. </label>
<input
required
type="text"
name="firstName"
ng-maxlength="3"
ng-model="dummy.firstName"
ow-model="$ctrl.state.firstName"
ng-change="$ctrl.handleChange(form.firstName)"
ng-model-options="{allowInvalid: true}"
/>
<p>
<label>This input is bound to $ctrl.state.firstName so it should update firstName</label>
<input
type="text"
name="dummy"
ng-model="dummy.foo"
ng-change="$ctrl.handleSecondChange(form.dummy)"
ng-model-options="{allowInvalid: true}"
/>
</p>
</form>
`;
}
}
const directive = () => ({
restrict: 'A',
require: 'ngModel',
scope: {
owModel: '<',
ngModel: '=',
},
link: (scope) => {
scope.$watch('owModel', (newVal) => {
// only apply change to ngModel if fModel has different
// value. This is an optimization
if (newVal !== scope.ngModel) {
scope.ngModel = newVal;
}
});
}
});
const owService = ['$timeout', ($timeout) => ({
// quick fix because when using: ng-model-options="{allowInvalid: true}"
// the sync validation happens after ngChange is fired.. unlike default value.
// @see https://github.com/angular/angular.js/issues/14043
onChange: fn => (...args) => $timeout(() => fn(...args))
})];
angular
.module('demo', [])
.component(App.declaration.selector, App.declaration)
.directive('owModel', directive)
.factory('owService', owService);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment