How do I keep react from stripping a-frame attributes? - reactjs

I have a short example of an a-frame page (without React) that uses the raycaster and cursor components. The HTML looks like this:
<a-scene>
<a-entity raycaster="objects: .clickable" cursor="rayOrigin: mouse"></a-entity>
<a-plane class="clickable" color="yellow" position="0 1.5 -3" onclick="handleClick()"></a-plane>
<a-sky color="blue"></a-sky>
</a-scene>`
When I render this HTML and view the DOM, I can see the raycaster and cursor attributes along with their data. According to the latest react docs, starting with React v16, unknown attributes on HTML elements should get passed through JSX. However, the attributes get stripped with the same HTML outputted through React, like this:
ReactDOM.render(
<a-scene>
<a-entity raycaster="objects: .clickable" cursor="rayOrigin: mouse"></a-entity>
<a-plane class="clickable" color="yellow" position="0 1.5 -3" onclick="handleClick()"></a-plane>
<a-sky color="blue"></a-sky>
</a-scene>,
document.getElementById('root')
);
If I inspect the DOM when this second react example is running, it looks like:<a-entity raycaster cursor></a-entity>
If I add "data-" to the front of the attribute name, it passes the data, but then it has the wrong name and a-frame doesn't see it. What am I doing wrong here?

That code will work:
<a-scene>
<a-entity raycaster="objects: .clickable" cursor="rayOrigin: mouse" />
<a-plane class="clickable" color="yellow" position="0 1.5 -3" onClick={handleClick} />
<a-sky color="blue" />
</a-scene>
The problem was that a-plane is not for React, so className doesn't work, but class - works.
But at the same time onclick="handleClick()" doesn't work, and onClick={handleClick} works.
Also there is another way to define what should be intersected:
raycaster="objects: [dataRaycastable]"
and then for example
<a-plane dataRaycastable={true} ... />

Related

How queryBy without html tags with React testing library

I use React testing library for my unit test.
I want to test this of my React component:
return (
<div>
<p data-testid="my-string">
{string}
</p>
</div>
);
After I query queryByTestId the component I receive something like:
<p class="css-1317scs-myString" data-testid="my-string"><iframe src="src="https://my-site.com?id=6533cf73&autoplay=false" allowfullscreen seamless frameborder="0" allow="encrypted-media"></iframe></p>
So with all the html tags etc.
expect(queryByTestId('my-string')).toBe(
'<iframe src="https://my-site.com?id=6533cf73&autoplay=false" allowfullscreen seamless frameborder="0" allow="encrypted-media"></iframe>'
);
I just want to test if <iframe src="https://my-site.com?id=6533cf73&autoplay=false" allowfullscreen seamless frameborder="0" allow="encrypted-media"></iframe> is exactly defined like this.
How do I get rid of all those html tags. Or do I have to use another approach?
To get the content of all the elements inside of the queried element, you should use textContent on the queried element.
expect(queryByTestId('my-string').textContent)
.toBe('<iframe src="src="https://my-site.com?id=6533cf73&autoplay=false" allowfullscreen seamless frameborder="0" allow="encrypted-media"></iframe>');
Yes, the rendered string in your component will swap out the < angle bracket character for <. React encodes the < and > characters automatically to prevent XSS attacks.
If you really want the brackets rendered, you can use React's dangerouslySetInnerHtml attribute. You can use it like so:
<p data-testid="my-string"
dangerouslySetInnerHTML={string}
></p>
After applying the dangerouslySetInnerHTML attribute, you should see the actual < brackets rendered in your app and in your test.

Angular material as foreignObject inside SVG

My general purpose is to make a dynamic and very simple flowchart view. I use svg and angular material. I am trying to show angular material objects like (md-select, md-menu, md-button) inside SVG. After a quick research I saw it is possible with "foreignObject" tags.
Secondly; I want to move all these elements at once inside SVG regarding mouse panning. So I use "viewBox" property.
In my sample;
I use "foreignObject" tag to show angular material "md-select" inside a svg element.
I expect "md-select" to move when I change x and y values of viewBox property of svg element but it keeps its position while clickable area changes.
When I try same scenario with html "select" it moves as I expect. But I can't do the same with angular material objects. (they visually stay in their original position but their click area goes another where regarding viexBox x-y values.)
<div ng-controller="MyCtrl">
x: <input ng-model="vbx">
y: <input ng-model="vby">
<svg id="processDesignPanel" viewBox="{{vbx}} {{vby}} 500 500" name="processDesignPanel" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="800px" height="800px">
<foreignObject width="100" height="50" x="100" y="100">
<md-select placeholder="Assign to user" ng-model="userkey" style="width: 200px;">
<md-option ng-repeat="user in formusers">{{user}}</md-option>
</md-select>
</foreignObject>
<foreignObject width="100" height="50" x="100" y="200">
<select placeholder="Assign to user" ng-model="userkey" style="width: 150px;">
<option ng-repeat="user in formusers">{{user}}</option>
</select>
</foreignObject>
</svg>
</div>
sample js
angular.module('MyApp', ['ngMaterial'])
.controller('MyCtrl', function ($scope) {
$scope.formusers=["ally","mike"];
$scope.vbx=null;
$scope.vby=null;
})
here is my fiddle.
This isn't a complete solution, but I think it's a couple steps in that direction. I cut down your fiddle to show the incorrectly-placed MD select along with the correctly-placed regular select, with a button that modifies the style of the md-select-value tag to have position:inherit and z-index:auto, which makes the MD select appear in the correct place. I don't know why it does this, yet, as I haven't delved into the lib's CSS.
document.getElementsByTagName('md-select-value')[0].setAttribute('style','z-index:auto; position:inherit')
https://jsfiddle.net/emamid/n8tr0gfk/6/

Flexbox with AngularJS 1.5 components

I have components created with ng-repeat and I want them to be flex children:
<div style="display:flex; flex-wrap: wrap">
<div ng-repeat="item in data" style="flex-basis: 30%">
<my-component item="item"></my-component>
</div>
<div>
Where my component's template is:
<div class="c">
...
</div>
It is kind of working, but the my-component items are not all in the same height as they would have been if they were simply divs.
I can workaround this by setting .c{height: 100%} but it messes up with the wrapping.
Can I acheive this behaviour with AngularJS 1.5 at all?
Attached codepen for repro: http://codepen.io/anon/pen/ENqvvO
Thanks!
The problem is that when using the component you have a new element wraping the div.c element, so that the flex behaviour doesn't bound the two elements of your css. Your example (from plunkr) without the component works because it doesn't have the my-component in between.
div.flex-container
my-component // <- this guy is breaking off the flex connection
div.c
In order to fix it you can style the tag my-component instead of .c so that the flex can be applied directly between div.flex-container and my-component.
Actually I recommend you to create a container component and an item component so that things are kept clear and solid.
For example:
<list>
<list-item>Item 1</list-item>
<list-item>Item 2</list-item>
<list-item>Item 3</list-item>
<list-item ng-repeat="item in items"> {{ item }} </list-item>
</list>
And also:
<gallery>
<gallery-item ng-repeat="photo in photos">
<photo img="photo "></photo>
</gallery-item>
</galery>
Beautiful, isn't it? :{D

ng-map and place autocomplete not working in modal

I am using ng-map directive and place autocomplete API in my angularjs application. which are working fine.
but the problem is I need Both in a bootstrap modal and when i am using same code in a bootstrap modal, Nothing is working neither ng-map nor place autocomplete.
Suggest me if I am missing something.
problem occures only when i use angular's ng-map directive. With javascript everything works fine but I don't want to write bulk of code. I wanna use ng-map only.
Here is my markup
<ng-map zoom="8">
<marker visible="true" centered="true" position="current-location" title="You are Here" draggable="true"></marker>
<marker visible="true" centered="true" position="{{vm.place.formatted_address}}" title="You are looking for this" draggable="true"></marker>
<marker ng-repeat="c in vm.cities" position="{{c.pos}}" title="{{c.name}}" id="{{c.id}}" on-click="vm.showCity(event, c)"></marker>
<directions
draggable="false"
travel-mode="DRIVING"
panel="p3"
origin="jaipur"
destination="Delhi">
</directions>
</ng-map>
see my
plunkr
for whole code
Since the map is displayed in bootstrap modal, the map needs to be explicitly intialized once the modal dialog is opened as demonstrated below:
$('#myModal').on('show.bs.modal', function(e) {
$timeout(function() {
google.maps.event.trigger(vm.dialogMap, 'resize');
vm.dialogMap.setCenter(vm.mapSettings.center);
vm.dialogMap.setZoom(vm.mapSettings.zoom);
});
});
'show.bs.modal' event is triggered once the modal is opened.
From another hand, unfortunately angularjs-google-maps at the moment contains a bug that prevents the route to be printed if multiple map instances are added into a page (in your example there are two map instances)
In the below example is provided a workaround.
Working example
The following forked plunker demonstrates how to:
properly display map in modal dialog
print routes in multiple map instances
add a style
.pac-container { z-index: 10000 !important; }
ref from there
Google Places Autocomplete not showing up
here a plnkr for a your working example
http://next.plnkr.co/edit/PrrKFvx3WbDFAXlk4ehH?p=preview

Analog of ngTransclude in Angular.Dart

I'm trying to figure out how to make a component render its children.
So I can compile:
<my-component>
<div id="child"></div>
</my-component>
into something like this:
<div id="parent">
<!-- some component stuff -->
<div id="child"></div>
</div>
Is there something like ngTransclude in Angular.Dart?
AngularDart uses Shadow DOM in place of ngTransclude. This is one of the ways we are pushing Angular into the browser with emerging web standards.
Adding a <content> tag instead your component's template will cause the child element to be placed there.
e.g. in your example <my-component>'s template might look like:
<div id="parent">
<!-- some component stuff -->
<content></content>
</div>
For even more awesomeness, you can use Shadow DOM's content selectors as well to control which child elements are displayed.

Resources