Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created April 1, 2015 13:01
Show Gist options
  • Save bennadel/d55de41cc985a48647fc to your computer and use it in GitHub Desktop.
Save bennadel/d55de41cc985a48647fc to your computer and use it in GitHub Desktop.
Mutating Isolate Scope References In AngularJS
<!doctype html>
<html ng-app="Demo">
<head>
<meta charset="utf-8" />
<title>
Mutating Isolate Scope References In AngularJS
</title>
</head>
<body ng-controller="AppController">
<h1>
Mutating Isolate Scope References In AngularJS
</h1>
<p>
You have {{ friends.length }} friends!
<!-- If you are friends with Kim, that's extra awesome. -->
<span ng-if="includesKim">That's awesome!</span>
</p>
<!--
Pass the friends collection into the LIST component directive which gives it a
two-way data binding to the collection. Also pass-in a method that can be used
to mutate said collection.
--
NOTE: The argument name being used in the addFriend() method - "item" - must
also be used in the isolate-scope component directive, otherwise, the value will
not be passed-in properly.
-->
<div bn-list="friends" add-item="addFriend( item )"></div>
<!-- This is the template for the component directive. -->
<script type="text/ng-template" id="list.htm">
<ul>
<li ng-repeat="item in collection">
{{ item }}
</li>
</ul>
</script>
<!-- Load scripts. -->
<script type="text/javascript" src="../../vendor/angularjs/angular-1.3.15.min.js"></script>
<script type="text/javascript">
// Create an application module for our demo.
var app = angular.module( "Demo", [] );
// -------------------------------------------------- //
// -------------------------------------------------- //
// I control the root of the application.
app.controller(
"AppController",
function( $scope ) {
// Start out with THREE items in the friends collection.
$scope.friends = [ "Sarah", "Joanna", "Heather" ];
// If we are friends with Kim, that's extra cool. Of course, looking at
// the local collection, we know that this won't be true at the time the
// Controller is instantiated.
$scope.includesKim = ( $scope.friends.indexOf( "Kim" ) !== -1 );
// ---
// PUBLIC METHODS.
// ---
// I push a new friend onto the collection.
$scope.addFriend = function( newFriend ) {
// Validate action.
if ( ! newFriend ) {
throw( new Error( "InvalidArgument" ) );
}
$scope.friends.push( newFriend );
// Now that we have a new friend, there may be a chance that we can
// turn on the friend-specific flag.
$scope.includesKim = ( $scope.friends.indexOf( "Kim" ) !== -1 );
};
}
);
// -------------------------------------------------- //
// -------------------------------------------------- //
// I provide a component directive for listing out items.
app.directive(
"bnList",
function() {
// Return the directive configuration object.
// --
// NOTE: We are creating an isolate scope with a two-way data binding to
// whatever reference is passed into the bn-list attribute. We are also
// expecting a method that can be used to mutate the isolated scope
// reference for said collection.
return({
link: link,
scope: {
collection: "=bnList",
mutateCollection: "&addItem"
},
templateUrl: "list.htm"
});
// I bind the JavaScript events to the local scope.
function link( scope, element, attributes ) {
// When we use the mutateCollection method to alter the bound
// collection, we have to use the "locals" object to bind a local
// value to the arguments list defined in the template. Meaning,
// the following key, "item", has to be the one used in the template
// that consumes this component directive.
scope.mutateCollection({
item: "Kim"
});
}
}
);
</script>
</body>
</html>
<!doctype html>
<html ng-app="Demo">
<head>
<meta charset="utf-8" />
<title>
Mutating Isolate Scope References In AngularJS
</title>
</head>
<body ng-controller="AppController">
<h1>
Mutating Isolate Scope References In AngularJS
</h1>
<p>
You have {{ friends.length }} friends!
<!-- If you are friends with Kim, that's extra awesome. -->
<span ng-if="includesKim">That's awesome!</span>
</p>
<!--
Pass the friends collection into the LIST component directive which gives it a
two-way data binding to the collection.
-->
<div bn-list="friends"></div>
<!-- This is the template for the component directive. -->
<script type="text/ng-template" id="list.htm">
<ul>
<li ng-repeat="item in collection">
{{ item }}
</li>
</ul>
</script>
<!-- Load scripts. -->
<script type="text/javascript" src="../../vendor/angularjs/angular-1.3.15.min.js"></script>
<script type="text/javascript">
// Create an application module for our demo.
var app = angular.module( "Demo", [] );
// -------------------------------------------------- //
// -------------------------------------------------- //
// I control the root of the application.
app.controller(
"AppController",
function( $scope ) {
// Start out with THREE items in the friends collection.
$scope.friends = [ "Sarah", "Joanna", "Heather" ];
// If we are friends with Kim, that's extra cool. Of course, looking at
// the local collection, we know that this won't be true when at the time
// the Controller is instantiated.
$scope.includesKim = ( $scope.friends.indexOf( "Kim" ) !== -1 );
}
);
// -------------------------------------------------- //
// -------------------------------------------------- //
// I provide a component directive for listing out items.
app.directive(
"bnList",
function() {
// Return the directive configuration object.
// --
// NOTE: We are creating an isolate scope with a two-way data binding to
// whatever reference is passed into the bn-list attribute.
return({
link: link,
scope: {
collection: "=bnList"
},
templateUrl: "list.htm"
});
// I bind the JavaScript events to the local scope.
function link( scope, element, attributes ) {
// CAUTION: Because the isolate scope provides for a two-way data
// binding to passed-in scope reference, this collection can now be
// mutated directly by the isolate directive. This is NOT a violation
// of the documentation in any way; but, it is likely a violation of
// good practices since the "owner" of the data is not aware that
// these changes are being made.
scope.collection.push( "Kim" );
}
}
);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment