Search code examples
data-bindingangular-cliaframewebvr

Databinding does not work for A-frame tag attributes


I'm making a WebVR application with and . I load some static JSON data from the assets and will bind it to an A-frame element. Here is an example of my JSON data.

{
    "id": 4,
    "image": "",
    "location": "Font",
    "nextScenes": [
        3,
        5
    ],
    "hotspots": [
        {
            "id": "obj1",
            "location": "2325 1305 -2400",
            "rotation": "-5 -50 -5",
            "scale": "150 150 150",
            "headerTitle": "",
            "body": ""
        },
        {
            "id": "obj2",
            "location": "3145 890 -2175",
            "rotation": "-5 -50 -5",
            "scale": "150 150 150",
            "headerTitle": "",
            "body": ""
        }
    ]
}

I'll load the hotspots in my HTML code with this code:

<a-scene inspector="url: https://aframe.io/releases/0.3.0/aframe-inspector.min.js">
    <a-assets>
        <img id="sky" [src]="currentImageSource" alt="" />
    </a-assets>

    <a-sky src="#sky"></a-sky>

    <!-- problems with code below -->
    <a-entity *ngFor="let spot of currentData.hotspots; let i = index" [id]="spot.id" 
              [position]="spot.location" [rotation]="spot.rotation" [scale]="spot.scale" 
              visible="true" mixin="null" color="pink" 
              text="zOffset:0;value:S;height:100;width:100;align:center"></a-entity>
</a-scene>

Notice that currentData is equal to the JSON code above and currentImageSource contains the location of the image.

The problem with code above is that the attributes position, rotation and scale wouldn't bind. In the rendered output are the variables empty but the ng-reflect-... attributes aren't empty.

Also if I inspect the code with ctrl + alt + I, the object got the a-entity tags the default values.

Update one: The databinding for the attribute id works.

Update two: Here you could see the output in my browser:

<app-vrtour _nghost-pub-1="">
  <a-scene class="fullscreen" inspector="" canvas="" keyboard-shortcuts="" screenshot="" vr-mode-ui="" auto-enter-vr="" _ngcontent-pub-1="">
    <a-assets _ngcontent-pub-1="">
      <ewalswebvr-static-assets _ngcontent-pub-1=""><img id="#details" crossorigin="anonymous" scr="/assets/images/details.jpg"></ewalswebvr-static-assets>
      <img id="sky" alt="" src="assets/360images/P5.tif" ng-reflect-src="assets/360images/P5.tif" _ngcontent-pub-1="">
    </a-assets>

    <!--template bindings={"ng-reflect-ng-for-of": "[object Object],[object Object]"}-->
    <!-- The two tags below are the lines that wouldn't bind -->
    <a-entity id="obj1" mixin="null" text="" ng-reflect-id="obj1" ng-reflect-position="2323.81 1305.90 -2400" ng-reflect-rotation="-4.58 -48.7 -5.16" ng-reflect-scale="150 150 150" ng-reflect-visible="true" position="" rotation="" scale="" visible=""
      _ngcontent-pub-1="" ng-reflect-color="#ff0000"></a-entity>
    <a-entity id="obj2" mixin="null" text="" ng-reflect-id="obj2" ng-reflect-position="3145.63 889.46 -2176.50" ng-reflect-rotation="-4.58 -48.7 -5.16" ng-reflect-scale="150 150 150" position="" rotation="" scale="" visible="" _ngcontent-pub-1=""
      ng-reflect-color="#00ff00"></a-entity>

    <a-sky src="#sky" material="" position="" rotation="" scale="" visible="" geometry="" _ngcontent-pub-1=""></a-sky>

    <canvas width="1920" height="930" class="a-canvas a-grab-cursor" style="width: 1920px; height: 930px;" data-aframe-canvas="true"></canvas>
    <div class="a-enter-vr" style="display: none;" aframe-injected=""><button class="a-enter-vr-button" aframe-injected=""></button></div>
    <div class="a-orientation-modal a-hidden" aframe-injected=""><button aframe-injected="">Exit VR</button></div>
    <a-entity aframe-injected="" position="" rotation="" scale="" visible="" camera="" wasd-controls="" look-controls="" data-aframe-inspector="default-camera"></a-entity>
    <a-entity aframe-injected="" position="" rotation="" scale="" visible="" light="" data-aframe-default-light=""></a-entity>
    <a-entity aframe-injected="" position="" rotation="" scale="" visible="" light="" data-aframe-default-light=""></a-entity>
    <a-entity position="" rotation="" scale="" visible="" camera=""></a-entity>
  </a-scene>

</app-vrtour>

Could you find the bug in my code?

Thanks in advance


Solution

  • After trying a workaround, I've found a solution that works. The issue of this code is that it didn't use databinding and I thing it is less performance that databinding but A-frame doesn't support it.

    Here you could find the code I've added in my typescript code:

    ngAfterViewInit(): void {
    
        for (let i: number = this.currentData.hotspots.length; i--;) {
    
            let spot: any = this.currentData.hotspots[i],
                el: any = document.getElementById(spot.id);
    
            el.setAttribute("position", spot.location);
            el.setAttribute("rotation", spot.rotation);
            el.setAttribute("scale", spot.scale);
        }
    }
    

    This code works if I give every a-entity-tag an unique ID. The HTML code of my component, is unchanged but it's possible to use this instead.

    <a-entity *ngFor="let spot of currentData.hotspots; let i = index" [id]="spot.id"
              text="zOffset:0;value:S;height:100;width:100;align:center"></a-entity>