mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
feat(ionContent): use child scope instead of isolate scope
Adds new '$ionicBind' service, which takes an object containing binding definitions (similar to angular directive isolate scope definition). Allows binding of any directive attribute & expressions from a scope, letting us do normal attribute -> scope binding without having to create isolate scopes. Closes #555. Closes #669
This commit is contained in:
61
js/ext/angular/src/directive/ionicContent.js
vendored
61
js/ext/angular/src/directive/ionicContent.js
vendored
@@ -18,33 +18,23 @@ angular.module('ionic.ui.content', ['ionic.ui.service', 'ionic.ui.scroll'])
|
||||
|
||||
// The content directive is a core scrollable content area
|
||||
// that is part of many View hierarchies
|
||||
.directive('ionContent', ['$parse', '$timeout', '$ionicScrollDelegate', '$controller', function($parse, $timeout, $ionicScrollDelegate, $controller) {
|
||||
.directive('ionContent', [
|
||||
'$parse',
|
||||
'$timeout',
|
||||
'$ionicScrollDelegate',
|
||||
'$controller',
|
||||
'$ionicBind',
|
||||
function($parse, $timeout, $ionicScrollDelegate, $controller, $ionicBind) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
template: '<div class="scroll-content"><div class="scroll" ng-transclude></div></div>',
|
||||
transclude: true,
|
||||
require: '^?ionNavView',
|
||||
scope: {
|
||||
onRefresh: '&',
|
||||
onRefreshOpening: '&',
|
||||
onScroll: '&',
|
||||
onScrollComplete: '&',
|
||||
refreshComplete: '=',
|
||||
onInfiniteScroll: '=',
|
||||
infiniteScrollDistance: '@',
|
||||
hasBouncing: '@',
|
||||
scroll: '@',
|
||||
padding: '@',
|
||||
hasScrollX: '@',
|
||||
hasScrollY: '@',
|
||||
scrollbarX: '@',
|
||||
scrollbarY: '@',
|
||||
startX: '@',
|
||||
startY: '@',
|
||||
scrollEventInterval: '@'
|
||||
},
|
||||
|
||||
scope: true,
|
||||
template:
|
||||
'<div class="scroll-content">' +
|
||||
'<div class="scroll"></div>' +
|
||||
'</div>',
|
||||
compile: function(element, attr, transclude) {
|
||||
if(attr.hasHeader == "true") { element.addClass('has-header'); }
|
||||
if(attr.hasSubheader == "true") { element.addClass('has-subheader'); }
|
||||
@@ -60,7 +50,31 @@ angular.module('ionic.ui.content', ['ionic.ui.service', 'ionic.ui.scroll'])
|
||||
|
||||
function prelink($scope, $element, $attr, navViewCtrl) {
|
||||
var clone, sc, scrollView, scrollCtrl,
|
||||
c = angular.element($element.children()[0]);
|
||||
scrollContent = angular.element($element[0].querySelector('.scroll'));
|
||||
|
||||
transclude($scope, function(clone) {
|
||||
scrollContent.append(clone);
|
||||
});
|
||||
|
||||
$ionicBind($scope, $attr, {
|
||||
onRefresh: '&',
|
||||
onRefreshOpening: '&',
|
||||
onScroll: '&',
|
||||
onScrollComplete: '&',
|
||||
refreshComplete: '=',
|
||||
onInfiniteScroll: '&',
|
||||
infiniteScrollDistance: '@',
|
||||
hasBouncing: '@',
|
||||
scroll: '@',
|
||||
padding: '@',
|
||||
hasScrollX: '@',
|
||||
hasScrollY: '@',
|
||||
scrollbarX: '@',
|
||||
scrollbarY: '@',
|
||||
startX: '@',
|
||||
startY: '@',
|
||||
scrollEventInterval: '@'
|
||||
});
|
||||
|
||||
if($scope.scroll === "false") {
|
||||
// No scrolling
|
||||
@@ -92,6 +106,7 @@ angular.module('ionic.ui.content', ['ionic.ui.service', 'ionic.ui.scroll'])
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//Publish scrollView to parent so children can access it
|
||||
scrollView = $scope.$parent.scrollView = scrollCtrl.scrollView;
|
||||
|
||||
|
||||
1
js/ext/angular/src/ionicAngular.js
vendored
1
js/ext/angular/src/ionicAngular.js
vendored
@@ -3,6 +3,7 @@
|
||||
* modules.
|
||||
*/
|
||||
angular.module('ionic.service', [
|
||||
'ionic.service.bind',
|
||||
'ionic.service.platform',
|
||||
'ionic.service.actionSheet',
|
||||
'ionic.service.gesture',
|
||||
|
||||
53
js/ext/angular/src/service/ionicBind.js
vendored
Normal file
53
js/ext/angular/src/service/ionicBind.js
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
angular.module('ionic.service.bind', [])
|
||||
.factory('$ionicBind', ['$parse', '$interpolate', function($parse, $interpolate) {
|
||||
var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/;
|
||||
return function(scope, attrs, bindDefinition) {
|
||||
angular.forEach(bindDefinition || {}, function (definition, scopeName) {
|
||||
//Adapted from angular.js $compile
|
||||
var match = definition.match(LOCAL_REGEXP) || [],
|
||||
attrName = match[3] || scopeName,
|
||||
mode = match[1], // @, =, or &
|
||||
parentGet,
|
||||
unwatch;
|
||||
|
||||
switch(mode) {
|
||||
case '@':
|
||||
if (!attrs[attrName]) {
|
||||
return;
|
||||
}
|
||||
attrs.$observe(attrName, function(value) {
|
||||
scope[scopeName] = value;
|
||||
});
|
||||
// we trigger an interpolation to ensure
|
||||
// the value is there for use immediately
|
||||
if (attrs[attrName]) {
|
||||
scope[scopeName] = $interpolate(attrs[attrName])(scope);
|
||||
}
|
||||
break;
|
||||
|
||||
case '=':
|
||||
if (!attrs[attrName]) {
|
||||
return;
|
||||
}
|
||||
unwatch = scope.$watch(attrs[attrName], function(value) {
|
||||
scope[scopeName] = value;
|
||||
});
|
||||
//Destroy parent scope watcher when this scope is destroyed
|
||||
scope.$on('$destroy', unwatch);
|
||||
break;
|
||||
|
||||
case '&':
|
||||
/* jshint -W044 */
|
||||
if (attrs[attrName] && attrs[attrName].match(RegExp(scopeName + '\(.*?\)'))) {
|
||||
throw new Error('& expression binding "' + scopeName + '" looks like it will recursively call "' +
|
||||
attrs[attrName] + '" and cause a stack overflow! Please choose a different scopeName.');
|
||||
}
|
||||
parentGet = $parse(attrs[attrName]);
|
||||
scope[scopeName] = function(locals) {
|
||||
return parentGet(scope, locals);
|
||||
};
|
||||
break;
|
||||
}
|
||||
});
|
||||
};
|
||||
}]);
|
||||
Reference in New Issue
Block a user