We are embarassingly bad at this in the tech industry.
Two options are presented, and third options are available, sometimes numerous options.
Two options are so similar, and cover such similar concerns, they are equally effective.
The two options don't even cover the same concerns, and therefore shouldn't really be compared.
Knockout
Backbone
Bootstrap
jQuery UI
Angular
Ember
Angular
React
Gulp
Grunt
Less
Sass
Bower
Browserify
"With angular, you are basically passing your data through these things called scopes. That's a very leaky abstraction. It forces you to compose an app, not in terms of functions and objects, but in terms of directives and their "flavor" of Model View Controller.
As you scale up, you start to miss the last 40 or 50 years of research of how to abstract a program"
- Pete Hunt
When selecting anything,
Ask yourself.
What does the tool abstract?
Directives are the lord of the dance. They are essentially a configuration object that takes all the other elements, and via magic and lazers turns them into declarative html.
angular
.module('angledditApp')
.directive('subredditMenuItem', function () {
return {
templateUrl: './partials/subreddit-menu-item.html',
restrict: 'E',
scope: {
subreddit: '@',
pages: '@',
renderer: '@'
},
link: function link($scope, $el, $attrs){
//dom manipulation would be here.
},
controller: function ($scope, $state, $stateParams) {
function navigate(subreddit, pages, renderer) {
$stateParams.pages = parseInt(pages);
$stateParams.subreddit = subreddit;
$state.go('angleddit.' + renderer, $stateParams);
}
$scope.navigate = navigate;
}
};
});
angular
.module('angledditApp')
.directive('subredditMenuItem', function () {
return {
templateUrl: './partials/subreddit-menu-item.html',
restrict: 'E',
scope: {
subreddit: '@',
pages: '@',
renderer: '@'
},
link: function link($scope, $el, $attrs){
//dom manipulation would be here.
},
controller: function ($scope, $state, $stateParams) {
function navigate(subreddit, pages, renderer) {
$stateParams.pages = parseInt(pages);
$stateParams.subreddit = subreddit;
$state.go('angleddit.' + renderer, $stateParams);
}
$scope.navigate = navigate;
}
};
});
<div ng-repeat="subreddit in subreddits" class=" btn btn-default">
<subreddit-Menu-Item
subreddit="{{subreddit.display_name}}"
pages="{{pages}}"
renderer = "{{renderer}}"
></subreddit-Menu-Item>
</div>
controller: function ($scope, $state, $stateParams) {
function navigate(subreddit, pages, renderer) {
$stateParams.pages = parseInt(pages);
$stateParams.subreddit = subreddit;
$state.go('angleddit.' + renderer, $stateParams);
}
$scope.navigate = navigate;
}
$scope
and
2 providers;
$state
and $stateParams are being injected into the controller
scope: {
subreddit: '@',
pages: '@',
renderer: '@'
}
<subreddit-Menu-Item
subreddit="{{subreddit.display_name}}"
pages="{{pages}}"
renderer = "{{renderer}}"
></subreddit-Menu-Item>
controller: function ($scope, $state, $stateParams) {
function navigate(subreddit, pages, renderer) {
$stateParams.pages = parseInt(pages);
$stateParams.subreddit = subreddit;
$state.go('angleddit.' + renderer, $stateParams);
}
$scope.navigate = navigate;
}
Scope, is essentailly like the public members of a revealing module. Public to the template itself, and modifiable via controller and link
@ DOM attr
= 2-way scope
& expression
The Dream
Create compositable, declarative components you just drop into a page and they work
<my-totallysick-dashboard data="data" />
<doin-things
data-ng-model="stuff"
data-ng-mouseover="hoverEdit = true"
data-ng-mouseleave="hoverEdit = false"
data-ng-class="{
'hover-class': hoverEdit,
'btn-green-on':allOn2,
'btn-green-off' : !allOn2,
visible: isPowerUser && !disabled,
enabled: isAdmin,
disabled: !isAdmin}"
data-ng-click="var1 = (allOn2==true ? allOn2 : !allOn2)"
data-ng-if="someCondition ? firdethisFunction(): orthisfunction()"
data-ng-directive ="coindition && condition2 && condition3 ? 4 : functionIfire()"
data-ng-another-directive
data-is-this-a-directive-or-just-an-attribute-lol
data-thenwho-was-scope
data-ng-ng-ng-nggggggggg-nggn-ngngngngngngg
></doin-things>
Implementation-wise what does this mean for you?
Not much, just use React and this happens automatically
(isnt new)
;(function ( $, window, document, undefined ) {
$.widget( "namespace.widgetName" , {
options: {
someValue: null
},
_create: function () {
this.element.addStuff();
},
destroy: function () {
$.Widget.prototype.destroy.call(this);
},
_privateMethod: function ( event ) {
console.log("_privateMethodcalled");
},
method: function ( event ) {
this._trigger("dataChanged", event, {
key: "someValue"
});
},
_setOption: function ( key, value ) {
switch (key) {
case "someValue":
//this.options.someValue = doSomethingWith( value );
break;
default:
//this.options[ key ] = value;
break;
}
$.Widget.prototype._setOption.apply( this, arguments );
}
});
})( jQuery, window, document );
State
and
Lifecycle
in
jQuery UI
AnguledditComponents.Test = React.createClass({
displayName: 'test-component',
propTypes: {
optionalArray: React.PropTypes.array,
optionalBool: React.PropTypes.bool,
value: React.PropTypes.string.isRequired
},
mixins: [someMixin, anotherMixin],
//lifecyclehooks
componentWillMount: function(){},
componentDidMount: function(){},
componentWillRecieveProps: function(){},
componentWillUpdate: function(){},
componentDidUpdate: function(){},
componentWillUnmount: function(){},
shouldComponentUpdate: function(){},
//init
getDefaultProps: function () {
return {
value: 'default value'
};
},
getInitialState: function () {},
__privateFunction: function(){},
//main entry point
render: function render() {
return React.DOM({
key: 'uniquekey'
}, 'contents');
}
});
State
and
Lifecycle
in
REACT
var HelloMessage = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
Maybe we could use them together to leverage the mutual advantages of each?
They both have strengths.
(for fabulous people)
git clone git@github.com:the-simian/OKCJS-December-2014-Angular-and-React.git
npm install
bower install
grunt serve
I get to pull it all together here.
Questions.
Discussion.
Tales of Triumph™
Synergy
jesseharlin.net
@5imian