Material: [md-sidenav] - support expressions in [md-component-id]

Created on 2 Oct 2015  路  4Comments  路  Source: angular/material

currently the following code will fail because [md-component-id] only supports strings:
_Html:_

<md-sidenav class="md-sidenav-left" md-component-id="side-{{vm.uid}}">
    Some Content
</md-sidenav>

_JS_:

$scope.vm = { uid: '1234-5678' };
$timeout(function(){
    $mdSidenav('side-' + $scope.vm.uid).open();
});

I'm not sure if the following is the acceptable fix, but it works:
replaced this line:

self.destroy = $mdComponentRegistry.register(self, $attrs.mdComponentId);

... with this:

$attrs.$observe('mdComponentId', function(val){ 
  self.destroy = $mdComponentRegistry.register(self, val);
}); 

Issue 3171 is possibly relevant since author also tries to set component id to a dynamic value.

merge ready bug

Most helpful comment

I use this as a workaround:

        .directive('evalAttrAsExpr', function evalAttrAsExpr() {
            /*
             * This directive is a workaround for the md-component-id attribute of the
             * mdSidenav directive.
             *
             * The mdSidenav directive, in its controller function, registers the element
             * using the md-component-id attribute. If we need this value to be an
             * expression to be evaluated in the scope, we can't do 
             *
             * <md-sidenav md-component-id="{{ expr }}" [...]>
             *
             * because the curly braces are replaced in a subsequent stage. To work around
             * this, this directive replace the value of md-component-id with the value of
             * that expression in the scope. So the previous example becomes
             *
             * <md-sidenav md-component-id="expr" eval-attr-as-expr="mdComponentId" [...]>
             */
            return {
                restrict: 'A',
                controller: function($scope, $element, $attrs) {
                    var attrToEval = $attrs.evalAttrAsExpr;
                    $attrs[attrToEval] = $scope.$eval($attrs[attrToEval]);
                },
                priority: 9999
            };
        })

Far from ideal, but fits the bill.

All 4 comments

I use this as a workaround:

        .directive('evalAttrAsExpr', function evalAttrAsExpr() {
            /*
             * This directive is a workaround for the md-component-id attribute of the
             * mdSidenav directive.
             *
             * The mdSidenav directive, in its controller function, registers the element
             * using the md-component-id attribute. If we need this value to be an
             * expression to be evaluated in the scope, we can't do 
             *
             * <md-sidenav md-component-id="{{ expr }}" [...]>
             *
             * because the curly braces are replaced in a subsequent stage. To work around
             * this, this directive replace the value of md-component-id with the value of
             * that expression in the scope. So the previous example becomes
             *
             * <md-sidenav md-component-id="expr" eval-attr-as-expr="mdComponentId" [...]>
             */
            return {
                restrict: 'A',
                controller: function($scope, $element, $attrs) {
                    var attrToEval = $attrs.evalAttrAsExpr;
                    $attrs[attrToEval] = $scope.$eval($attrs[attrToEval]);
                },
                priority: 9999
            };
        })

Far from ideal, but fits the bill.

Is it just in md-component-id or inside whole tag?
If you write any angular expression in inner HTML of it doesn't work, meanwhile if I use ng-bind instead, it works.

+1

This issue is closed as part of our 鈥楽urge Focus on Material 2' efforts.
For details, see our forum posting @ http://bit.ly/1UhZyWs.

Was this page helpful?
0 / 5 - 0 ratings