diff --git a/lib/core_dom/element_binder.dart b/lib/core_dom/element_binder.dart index f6de44a12..df464e4ee 100644 --- a/lib/core_dom/element_binder.dart +++ b/lib/core_dom/element_binder.dart @@ -224,9 +224,10 @@ class ElementBinder { Http http = injector.get(Http); TemplateCache templateCache = injector.get(TemplateCache); DirectiveMap directives = injector.get(DirectiveMap); + NgBaseCss baseCss = injector.get(NgBaseCss); // This is a bit of a hack since we are returning different type then we are. var componentFactory = new _ComponentFactory(node, ref.type, component, - injector.get(dom.NodeTreeSanitizer), _expando); + injector.get(dom.NodeTreeSanitizer), _expando, baseCss); var controller = componentFactory.call(injector, scope, viewCache, http, templateCache, directives); diff --git a/lib/core_dom/module_internal.dart b/lib/core_dom/module_internal.dart index 6a1c8628a..450dd272f 100644 --- a/lib/core_dom/module_internal.dart +++ b/lib/core_dom/module_internal.dart @@ -15,6 +15,8 @@ import 'package:angular/core_dom/dom_util.dart' as util; import 'package:angular/change_detection/watch_group.dart' show Watch, PrototypeMap; import 'package:angular/core/registry.dart'; +import 'package:angular/directive/module.dart' show NgBaseCss; + part 'animation.dart'; part 'view.dart'; part 'view_factory.dart'; diff --git a/lib/core_dom/view_factory.dart b/lib/core_dom/view_factory.dart index a82817dcd..603e444cf 100644 --- a/lib/core_dom/view_factory.dart +++ b/lib/core_dom/view_factory.dart @@ -155,6 +155,7 @@ class _ComponentFactory implements Function { final NgComponent component; final dom.NodeTreeSanitizer treeSanitizer; final Expando _expando; + final NgBaseCss _baseCss; dom.ShadowRoot shadowDom; Scope shadowScope; @@ -162,7 +163,7 @@ class _ComponentFactory implements Function { var controller; _ComponentFactory(this.element, this.type, this.component, this.treeSanitizer, - this._expando); + this._expando, this._baseCss); dynamic call(Injector injector, Scope scope, ViewCache viewCache, Http http, TemplateCache templateCache, @@ -178,7 +179,7 @@ class _ComponentFactory implements Function { // so change back to using @import once Chrome bug is fixed or a // better work around is found. List> cssFutures = new List(); - var cssUrls = component.cssUrls; + var cssUrls = []..addAll(_baseCss.urls)..addAll(component.cssUrls); if (cssUrls.isNotEmpty) { cssUrls.forEach((css) => cssFutures.add(http .getString(css, cache: templateCache) diff --git a/lib/directive/module.dart b/lib/directive/module.dart index d5187a6b4..2375c5e8a 100644 --- a/lib/directive/module.dart +++ b/lib/directive/module.dart @@ -20,6 +20,7 @@ import 'package:angular/change_detection/watch_group.dart'; import 'package:angular/change_detection/change_detection.dart'; part 'ng_a.dart'; +part 'ng_base_css.dart'; part 'ng_bind.dart'; part 'ng_bind_html.dart'; part 'ng_bind_template.dart'; @@ -45,6 +46,7 @@ part 'ng_model_validators.dart'; class NgDirectiveModule extends Module { NgDirectiveModule() { value(NgA, null); + type(NgBaseCss); // The root injector should have an empty NgBaseCss value(NgBind, null); value(NgBindTemplate, null); value(NgBindHtml, null); diff --git a/lib/directive/ng_base_css.dart b/lib/directive/ng_base_css.dart new file mode 100644 index 000000000..553af61c8 --- /dev/null +++ b/lib/directive/ng_base_css.dart @@ -0,0 +1,14 @@ +part of angular.directive; + +@NgDirective( + selector: '[ng-base-css]', + visibility: NgDirective.CHILDREN_VISIBILITY +) +class NgBaseCss { + List _urls = const []; + + @NgAttr('ng-base-css') + set urls(v) => _urls = v is List ? v : [v]; + + List get urls => _urls; +} diff --git a/test/directive/ng_base_css_spec.dart b/test/directive/ng_base_css_spec.dart new file mode 100644 index 000000000..0590ff6ad --- /dev/null +++ b/test/directive/ng_base_css_spec.dart @@ -0,0 +1,73 @@ +library ng_base_css_spec; + +import '../_specs.dart'; + +@NgComponent( + selector: 'html-and-css', + templateUrl: 'simple.html', + cssUrl: 'simple.css') +class _HtmlAndCssComponent {} + +main() => describe('NgBaseCss', () { + beforeEachModule((Module module) { + module + ..type(_HtmlAndCssComponent); + }); + + it('should load css urls from ng-base-css', async((TestBed _, MockHttpBackend backend) { + backend + ..expectGET('base.css').respond('.base{}') + ..expectGET('simple.css').respond('.simple{}') + ..expectGET('simple.html').respond('
Simple!
'); + + var element = e('
ignore
'); + _.compile(element); + + backend.flush(); + microLeap(); + + expect(element.children[0].shadowRoot).toHaveHtml( + '
Simple!
' + ); + })); + + it('ng-base-css should overwrite parent ng-base-csses', async((TestBed _, MockHttpBackend backend) { + backend + ..expectGET('base.css').respond('.base{}') + ..expectGET('simple.css').respond('.simple{}') + ..expectGET('simple.html').respond('
Simple!
'); + + var element = e('
ignore
'); + _.compile(element); + + backend.flush(); + microLeap(); + + expect(element.children[0].children[0].shadowRoot).toHaveHtml( + '
Simple!
' + ); + })); + + describe('from injector', () { + beforeEachModule((Module module) { + module.value(NgBaseCss, new NgBaseCss()..urls = ['injected.css']); + }); + + it('ng-base-css should be available from the injector', async((TestBed _, MockHttpBackend backend) { + backend + ..expectGET('injected.css').respond('.injected{}') + ..expectGET('simple.css').respond('.simple{}') + ..expectGET('simple.html').respond('
Simple!
'); + + var element = e('
ignore
'); + _.compile(element); + + backend.flush(); + microLeap(); + + expect(element.children[0].shadowRoot).toHaveHtml( + '
Simple!
' + ); + })); + }); +});