Skip to content

Commit 90f792d

Browse files
committed
Assignable expressions enhancement
1 parent c175656 commit 90f792d

File tree

2 files changed

+30
-13
lines changed

2 files changed

+30
-13
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,11 @@ Some of the properties offered by the adapter can also be accessed directly from
8383

8484
The `expression` can be any angular expression (assignable expression where so specified). All expressions are evaluated once at the time when the scroller is initalized. Changes in the expresion value after scroller intialization will have no impact on the scroller behavior.
8585

86-
The assignable expressions will be used by scroller to inject the requested value into the target scope. The scope associated with the viewport (the element marked with the [uiScrollViewport](#uiscrollviewport-directive) directive) will be used as the target scope. If the viewport is not defined (window viewport), the $rootScope will be used as the target scope.
86+
The assignable expressions will be used by scroller to inject the requested value into the target scope. The scope associated with the viewport (the element marked with the [uiScrollViewport](#uiscrollviewport-directive) directive) will be used as the target scope. If the viewport is not defined (window viewport), the $rootScope will be used as the target scope. Note that the nearest additional scope-wrapper (like ng-if directive set right on the viewport) makes this mechanism unusable. There are two options which help in this case:
8787

88-
The second format `expression on controller` can be used to explicitly target the scope associated with the specified controller as the target scope for the injection. In this format `expression` is any angular assignable expression, and `controller` is the name of controller constructor function as specified in the `ng-controller` directive. The scroller will traverse its parents to locate the target scope associated with the specified controller.
88+
1. The second format `expression on controller` can be used to explicitly target the scope associated with the specified controller as the target scope for the injection. In this format `expression` is any angular assignable expression, and `controller` is the name of controller constructor function as specified in the `ng-controller` directive. The scroller will traverse its parents to locate the target scope associated with the specified controller.
89+
90+
2. Also `Controller As` syntax could be used as an alternative way to specify target controller in assignable expressions.
8991

9092
###Data Source
9193
Data source is an object to be used by the uiScroll directive to access the data.

src/ui-scroll.js

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ angular.module('ui.scroll', [])
416416
return viewport;
417417
}
418418

419-
function Adapter($attr, viewport, buffer, adjustBuffer) {
419+
function Adapter($attr, viewport, buffer, adjustBuffer, element) {
420420
const viewportScope = viewport.scope() || $rootScope;
421421
let disabled = false;
422422
let self = this;
@@ -512,21 +512,36 @@ angular.module('ui.scroll', [])
512512
if (!match)
513513
throw new Error('Expected injection expression in form of \'target\' or \'target on controller\' but got \'' + expression + '\'');
514514
let target = match[1];
515-
let controllerName = match[2];
516-
if (controllerName) {
517-
let candidate = viewport;
518-
scope = undefined;
515+
let onControllerName = match[2];
516+
517+
let parseControllers = (controllerName, as = false) => {
518+
let candidate = element;
519519
while (candidate.length) {
520520
let candidateName = (candidate.attr('ng-controller') || '').match(/(\w(?:\w|\d)*)(?:\s+as\s+(\w(?:\w|\d)*))?/);
521-
if (candidateName && candidateName[1] === controllerName) {
521+
if (candidateName && candidateName[as ? 2 : 1] === controllerName) {
522522
scope = candidate.scope();
523523
break;
524524
}
525525
candidate = candidate.parent();
526526
}
527-
if (!scope)
528-
throw new Error('Failed to locate target controller \'' + controllerName + '\' to inject \'' + target + '\'');
527+
};
528+
529+
if (onControllerName) { // 'on' syntax parsing
530+
scope = null;
531+
parseControllers(onControllerName);
532+
if (!scope) {
533+
throw new Error('Failed to locate target controller \'' + onControllerName + '\' to inject \'' + target + '\'');
534+
}
529535
}
536+
else { // try to parse with 'Controller As' syntax
537+
let controllerAsName;
538+
let dotIndex = target.indexOf('.');
539+
if(dotIndex > 0) {
540+
controllerAsName = target.substr(0, dotIndex);
541+
parseControllers(controllerAsName, true);
542+
}
543+
}
544+
530545
assign = $parse(target).assign;
531546
}
532547
return (value) => {
@@ -564,9 +579,9 @@ angular.module('ui.scroll', [])
564579
function link($scope, element, $attr, controllers, linker) {
565580

566581
const match = $attr.uiScroll.match(/^\s*(\w+)\s+in\s+([(\w|\$)\.]+)\s*$/);
567-
568-
if (!(match))
582+
if (!match) {
569583
throw new Error('Expected uiScroll in form of \'_item_ in _datasource_\' but got \'' + $attr.uiScroll + '\'');
584+
}
570585

571586
function parseNumericAttr(value, defaultValue) {
572587
let result = $parse(value)($scope);
@@ -590,7 +605,7 @@ angular.module('ui.scroll', [])
590605

591606
let buffer = new Buffer(bufferSize);
592607
let viewport = new Viewport(buffer, element, viewportController, padding);
593-
let adapter = new Adapter($attr, viewport, buffer, adjustBuffer);
608+
let adapter = new Adapter($attr, viewport, buffer, adjustBuffer, element);
594609
if (viewportController)
595610
viewportController.adapter = adapter;
596611

0 commit comments

Comments
 (0)