react-native-webview and array list - react-native

I'm using react-native-webview and another page I can render a static webview like this:
return `<html>
<head>
<style>
.t-center{
text-align: center;
</style>
</head>
<body>
<div class="t-center">
<h1>GUIA DE AGENDAMENTO - ENTREGA</h1>
<h1>0000000</h1>
</div>
</body>
</html>`
But now I need to render a list of items from an array inside a webview. I tried using the map but it didn't work:
return items.map((item) => {
return `<html>
<head>
<style>
.t-center{
text-align: center;
</style>
</head>
<body>
<div class="t-center">
<h1>GUIA DE AGENDAMENTO - ENTREGA</h1>
<h1>${item.namE_CLI}</h1>
</div>
</body>
</html>`;
});

here is the solution where you can find the props value injectedJavaScript which helps to inject JavaScript to webview. sample code given below how to add array list to webview.
ex:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { WebView } from 'react-native-webview';
const App = () => {
let myList = `["A", "B", "C", "D"]`;
const overrideJs = `
let $buttons = $('<div id="buttonGallery">');
let myList = ${myList}
let myColors = ["red", "green", "blue", "red"];
myList.map(function(letter, index) {
let $button = $("<div></div>")
.addClass("buttons")
.attr("id", "button_" + letter)
.html("<p>" + letter + "</p>")
.on("mouseenter", function() {
$(this).css("background", myColors[index]);
})
.on("mouseleave", function() {
if (!$(this).hasClass('clicked')) {
$(this).css("background", "transparent");
}
})
.on("click", function() {
$(this).css("background", myColors[index]);
$(this).addClass('clicked');
})
$buttons.append($button);
});
$("body").append($buttons);
$("#done").on("click", clearColor);
function clearColor() {
$(".buttons").css({
backgroundColor: 'transparent'
});
$(".buttons").removeClass('clicked');
}
`
const html = `<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<style media="screen">
.buttons {
width: 150px;
height: 50px;
border: solid 2px black;
text-align: center;
color: black;
cursor: pointer;
background-color: white;
margin: 2px;
}
#buttonGallery {
margin: 10px;
padding: 10px;
border: solid 2px black;
width: 155px;
}
#done {
width: 150px;
height: 50px;
border: solid 2px black;
text-align: center;
color: black;
cursor: pointer;
background-color: white;
margin: 2px;
}
</style>
</head>
<body>
<div id="done">
<p>done</p>
</div>
</body>
</html>
`
return (
<View style={{ flex: 1, backgroundColor: 'red' }}>
<WebView
ref={(r) => this.webviewRef = r}
source={{ html }}
// onMessage={}
injectedJavaScript={overrideJs}
injectedJavaScriptForMainFrameOnly={false}
allowUniversalAccessFromFileURLs={true}
/>
</View>
)
};
export default App;

Thanks Virendrasinh R, your propose is very good! But I found a way to do this with map and toString():
const names = items.map(function (item) {
return `<div class="row"><span class="title">${item["idcont"]} - ${item["nomE_CLI"]}</span></div>
<div class="row"><strong>Tipo:</strong> ${item["tipO_CONHECIMENTO"]}</div>
<div class="row"><strong>ContĂȘiner:</strong> ${item["idcont"]}</div>
<div class="row"><strong>N:</strong> ${item["numerO_CE_MERCANTE"]}</div>
<div class="row"><strong>Status:</strong> ${item["status"]}</div>
<div class="row"><strong>Data Status:</strong> ${item["datA_STATUS"]}</div>
<div class="row"><strong>Data Prevista:</strong> ${item["dH_PREV_INSPECAO"]}</div>
<div class="row last-row"><strong>Data Descarga:</strong> ${item["dH_DESCARGA"]}</div>
`;
});
const html = `
<html>
<head>
<style>
body{
padding: 0 25px;
}
.row{
font-size: 38px;
border-bottom: 1px solid ${theme.color.gray};
padding: 10px;
}
.last-row{
margin-bottom: 50px;
}
.title{
color: ${theme.color.success};
font-size: 48px;
font-weight: bold;
}
strong{
color: ${theme.color.primary};
}
</style>
</head>
<body>${names.toString()}</body>
</html>
`;

Related

How to anchor position popup to left screen in openlayers 6

I have a popup when click to layer on map and popup displayed at selected position. I want to show popup to left screen, how can i do that. Please help me, my english not good. Thanks
My popup show like this
Popup here
I want when click popup will show left screen, not center
If you want the popup on center left, you could do it like this:
<html>
<head>
<meta charset="utf-8" />
<style>
.map {
height: 100%;
width: 100%;
}
html,
body {
height: 100%
}
.ol-popup {
background-color: white;
box-shadow: 0 1px 4px rgba(0,0,0,0.2);
padding: 15px;
border-radius: 10px;
border: 1px solid #cccccc;
bottom: 12px;
min-width: 280px;
}
.ol-popup:after {
border-top-color: white;
border-width: 10px;
left: 48px;
margin-left: -10px;
}
.ol-popup:before {
border-top-color: #cccccc;
border-width: 11px;
left: 48px;
margin-left: -11px;
}
</style>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.13.0/build/ol.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.13.0/css/ol.css">
</head>
<body>
<div id="popup" class="ol-popup">
<div id="popup-content"></div>
</div>
<div id="map" class="map"></div>
<script type="text/javascript">
const container = document.getElementById('popup');
const content = document.getElementById('popup-content');
document.addEventListener("DOMContentLoaded", function () {
drawMap();
});
function drawMap() {
const osmLayer = new ol.layer.Tile({
source: new ol.source.OSM({
attributions: '© OpenStreetMap',
})
});
map = new ol.Map({
target: 'map',
layers: [
osmLayer,
],
view: new ol.View(),
});
const popup = new ol.Overlay({
element: document.getElementById('popup'),
});
map.addOverlay(popup);
map.getView().fit([0,0,0,0]);
map.on('click', function (evt) {
const element = popup.getElement();
const popupMap = popup.getMap();
const coordinate = evt.coordinate;
const viewExtent = popupMap.getView().calculateExtent();
const centerPoint = ol.extent.getCenter(viewExtent);
content.innerHTML = '<p>You clicked here:</p><code>' + coordinate + '</code>';
popup.setPosition( [viewExtent[0], centerPoint[1]] );
});
}
</script>
</body>
</html>
Remove position absolute and determine the position:
https://jsfiddle.net/ve5mn0by/5/
EDIT:
without Openlayers Overlay, just HTML:
map.on('click', function (evt) {
const container = document.createElement('div');
const content = document.createElement('div');
container.style.width = '10rem';
container.style.height = '100%'
//container.style.backgroundColor = '#FF0000';
container.style.position = 'absolute';
container.style.display = 'flex';
content.style.width = '100%';
content.style.height = '10rem'
content.style.backgroundColor = '#FFFF00';
content.style.alignSelf = 'center';
container.appendChild(content);
document.body.appendChild(container);
});

Styles are not being applied to elements created in the setup function in vue

So I am working on this mini website and I'm trying to not hard code repetitive elements in the template, so I thought I would a function to display them all.
<template>
<div class="wrapper">
<div class="skills" ref="canvas">
</div>
</div>
import { ref, onMounted } from 'vue';
import MySkills from '../constants/skills';
export default {
setup() {
const skills = MySkills
const canvas = ref(null);
const displaySkills = () => {
skills.forEach(skill => {
const el = document.createElement('div');
el.className = 'skill';
el.innerText = skill.name;
const level = document.createElement('span');
level.className = 'level';
level.innerText = skill.level;
el.appendChild(level);
canvas.value.appendChild(el);
})
}
onMounted(() => {
displaySkills();
})
return {
canvas,
displaySkills
}
}
}
the styles are in a separate file
.skill {
padding: 10px;
border-radius: 100px;
text-align: center;
position: relative;
background-color: aqua;
}
.level {
position: absolute;
top: -5%;
left: 0%;
padding: 5px;
border-radius: 100px;
text-align: center;
}
Now the ssue is that those styles are not being applied the el and level elements
please help!!!
You should not access the DOM (createElement, appendChild) while working with Vue.
If you are new to Vue, v-for does exactly that, more info in the official docs.
So your code would be:
<template>
<div class="wrapper">
<!-- you should put a unique identifier in the key tag, if you don't have an id the name should be fine too -->
<div class="skills" v-for="skill in MySkills" :key="skill.id">
<your-skill-html>
{{ skill.name }} etc
</your-skill-html>
</div>
</div>
</template>
<script setup>
import MySkills from '../constants/skills';
</script>
<style>
.skill {
padding: 10px;
border-radius: 100px;
text-align: center;
position: relative;
background-color: aqua;
}
.level {
position: absolute;
top: -5%;
left: 0%;
padding: 5px;
border-radius: 100px;
text-align: center;
}
/* or import "path/to/my-css-file.css" */
</style>
Please note that I'm using the script setup syntax but it's not required, it's just quicker to write since you can omit the defineComponent part and the return values.

How can i change style of the body when my modal it will be open?

How can i change the body{overflow:hidden} when my modal it will be open?
for example it will be my modal, when its open, i would like to apply this style body{overflow:hidden}
<div v-if="dialogFoundation">
i am using vuejs3, i am using setup(){...}
The best performance would be to use javascript plain. You can add Eventlistener top the modal trigger Element. In my example i use a button. If it triggered then you can use classList and assign the body a class. In my example .dark.
Vue version
<!-- Use preprocessors via the lang attribute! e.g. <template lang="pug"> -->
<template>
<div id="app">
<h1>{{message}}</h1>
<p></p>
<button #click="doSomething">Modal</button>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Welcome to Vue!'
};
},
methods: {
doSomething() {
const b = document.querySelector('body');
b.classList.toggle('dark');
}
}
};
</script>
<!-- Use preprocessors via the lang attribute! e.g. <style lang="scss"> -->
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
a,
button {
color: #4fc08d;
}
button {
background: none;
border: solid 1px;
border-radius: 2em;
font: inherit;
padding: 0.75em 2em;
}
.dark {
background: black;
opacity: 0.4;
}
</style>
Vanilla JS
const btn = document.querySelector('button');
btn.addEventListener('click', () => {
const b = document.querySelector('body');
b.classList.toggle('dark');
})
.dark {
background: black;
opacity: 0.4;
}
<body>
<div></div>
<button>click</button>
</body>
You can use watchers in Vue.js for solving this problem.
When variables changes you can check whether it is true or not, and if true change overflow of body to hidden.
{
watch: {
dialogFoundation(dialogFoundation) {
document.body.style.overflow = dialogFoundation ? "hidden" : "auto"
}
}
}
But I think this is not good solution. You can set this styles to your app element
#app {
width: 100%;
height: 100%;
overflow: auto;
}
and you can change style of app element using Vue directives.
<template>
<div id="app" :class="{ hidden: dialogFoundation }">
Long text....
</div>
</template>
<script>
import { ref } from "vue";
export default {
setup() {
const dialogFoundation = ref(true);
return { dialogFoundation };
},
};
</script>
<style>
html,
body,
#app {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
box-sizing: border-box;
}
#app {
overflow: auto;
}
#app.hidden {
overflow: hidden;
}
</style>
Code in codesandbox - https://codesandbox.io/s/immutable-glitter-rwc2iy?file=/src/App.vue

To immediately change columns and rows of a table by entering numbers in the Vue

After adding and entering a button, I implemented changing the table by pressing the button, but I want to change the column and row of the table immediately as soon as I enter the number. For example, if I enter 4, I want to have a 4X4 table. I don't know. Help me.
<html>
<head>
<meta charset="utf-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
div { padding: 30px; margin: 30px auto; width: 600px;
border: 1px solid #ccc; box-shadow: 3px 3px 3px #aaa; }
table { border-collapse: collapse; margin-top: 10px; }
td { width: 50px; height: 50px; border: 1px solid gray; font-size: 20pt;
text-align: center; cursor: pointer; }
.yellow { background-color: yellow; }
</style>
</head>
<body>
<div id="app">
<input type="text" v-model.number="size" >
<button type="button" #click="change(size)">Change</button>
<table :style="{backgroundColor: color}">
<tr v-for="(row, index1) in matrix" v-bind:key="index1">
<td v-for="(value, index2) in row" v-bind:key="index2">
{{ value }}
</td>
</tr>
</table>
<h1>{{size}}</h1>
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
size: 3,
matrix: [],
clicked: [],
color: "",
},
created() {
for (let r = 0; r < this.size; ++r) {
this.matrix[r] = [];
for (let c = 0; c < this.size; ++c)
this.matrix[r][c] = r * this.size + c +1;
}
},
methods:{
change(s){
this.size=s
console.log(this.size)
let arr=[]
for (let r = 0; r < this.size; ++r) {
arr[r] = [];
for (let c = 0; c < this.size; ++c)
arr[r][c] = r * this.size + c +1;
}
this.matrix=arr
}
}
})
</script>
</body>
</html>
you can using a watcher on your size state
the watch statement should be like this:
watch: {
size(newVal){
this.change(newVal)
}
}
and you can see a working example in the below :)
var app = new Vue({
el: '#app',
data: {
size: 3,
matrix: [],
clicked: [],
color: "",
},
created() {
this.change(this.size)
},
methods:{
change(s){
console.log(this.size)
let arr=[]
for (let r = 0; r < this.size; ++r) {
arr[r] = [];
for (let c = 0; c < this.size; ++c)
arr[r][c] = r * this.size + c +1;
}
this.matrix=arr
}
},
watch: {
size(newVal){
this.change(newVal)
}
}
})
div { padding: 30px; margin: 30px auto; width: 600px;
border: 1px solid #ccc; box-shadow: 3px 3px 3px #aaa; }
table { border-collapse: collapse; margin-top: 10px; }
td { width: 50px; height: 50px; border: 1px solid gray; font-size: 20pt;
text-align: center; cursor: pointer; }
.yellow { background-color: yellow; }
<html>
<head>
<meta charset="utf-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model.number="size" >
<table :style="{backgroundColor: color}">
<tr v-for="(row, index1) in matrix" v-bind:key="index1">
<td v-for="(value, index2) in row" v-bind:key="index2">
{{ value }}
</td>
</tr>
</table>
<h1>{{size}}</h1>
</div>
</body>
</html>

vue js use npm module as inline script

I am not using webpack, I include vue as external script Something like this:
<script src ="unpckg.com/vue.js-latest"></script>
And I want to use npm module
https://github.com/stephan281094/vue-drag-select
So I include it like this:
<script src= "https://unpkg.com/vue-drag-select#0.1.5/dist/vue-drag-select.js
"></script>
How do I use it?
UPD: I corrected the path to external script.
My question is how to include vue-drag-select component in my app because
When I write
import DragSelect from 'vue-drag-select/src/DragSelect.vue'
It gives me an error because I don't use webpack, so there is no import function
This is just a url https://github.com/stephan281094/vue-drag-select to dispaly package details not any file path
Here is the raw data of .js file might be you want to include, go this url and save contents of this file in your local and then import/include
https://github.com/stephan281094/vue-drag-select/blob/master/dist/vue-drag-select.js
If you include cdn script, then DragSelect is global variable, you can access it directly
Vue.component('vue-drag-select', DragSelect.default)
Vue.component('vue-drag-select', DragSelect.default)
new Vue({
el: "#app1",
methods: {
getClasses (item, selectedItems) {
const isActive = !!(selectedItems.find((selectedItem) => {
return parseInt(selectedItem.dataset.item, 10) === item
}))
return {
item: true,
active: isActive
}
}
}
})
*,
*:before,
*:after {
box-sizing: inherit;
}
html {
box-sizing: border-box;
user-select: none;
}
html,
body {
margin: 0;
padding: 0;
min-height: 100vh;
}
body {
font: 16px / 1.5 'Helvetica Neue', sans-serif;
padding: 5%;
}
/* Custom styling */
.item {
display: inline-flex;
min-width: 80px;
height: 100px;
margin-right: 10px;
margin-bottom: 10px;
background-color: #ddd;
justify-content: center;
align-items: center;
text-transform: uppercase;
letter-spacing: 3px;
font-size: 10px;
}
.item.active {
background-color: rgb(0, 162, 255);
color: #fff;
}
<script src="https://unpkg.com/vue-drag-select#0.1.5/dist/vue-drag-select.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app1">
<h1>Vue Drag Select Example</h1>
<vue-drag-select selector-class="item">
<template slot-scope="{ selectedItems }">
<div
v-for="item in 50"
:class="getClasses(item, selectedItems)"
:data-item="item"
>
Item {{ item }}
</div>
</template>
</vue-drag-select>
</div>