How to remove markers in react-google-maps - react-google-maps

I create my markers like this, a recurisve function call every 5 seconds to
change layers on the map.
var MeterLocations= Object.keys(dict)
var currloc = 0;
var markers;
function cycleMeteors(callback){
markers = dict[MeterLocations[currloc]].map(function(arr,i){
return(
<Marker
icon={purpleS}
key={i+"marker-num"+MeterLocations[currloc]}
position={{ lat: parseFloat(arr.val[4]),
lng: parseFloat(arr.val[5]) }}
/>)
})
currloc +=1;
setTimeout(function(){
callback(markers);
},5000);
}
I attempt here to remove the markers from the map by popping the entire array into length = 0. but that does not remove the markers from the map. another post mentioned settng the map to null map[map.length-1].setMap(null) but that doesnt work in reactjs
var [map, setMap] = useState([]);
cycleMeteors(function(s){
console.log(s.length);
while(map.length){
console.log(map.length)
map.pop()
}
// s is the new array of markers
setMap(s);
})
idk if you need this but here is my app.js
const MapWithAMarker = withScriptjs(withGoogleMap(props => {
console.log(props.children);
return (
<GoogleMap
defaultZoom={2}
defaultCenter={{ lat: 0, lng: 0 }}
>
{props.children.length ? props.children : []}
</GoogleMap>
)
}));
function App() {
var [map, setMap] = useState({});
cycleMeteors(function(s){
console.log(s.length);
while(map.length){
console.log(map.length)
map[map.length-1].setMap(null)
map.pop()
}
setMap(s);
})
return (
<div className="App">
<article>
<div id="maps-widget">
</div>
</article>
<article>
<h4>Data stuff</h4>
<p> These items amount of </p>
<p> Metory type | number in class </p>
{/*<MClassView data={dict}/>
*/}
<MapWithAMarker
googleMapURL={`https://maps.googleapis.com/maps/api/js?key=${apikey}&v=3.exp&libraries=geometry,drawing,places`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `600px`, width: "1000px" }} />}
mapElement={<div style={{ height: `100%` }} />}
>{map}</MapWithAMarker>
</article>
</div>
);
}

Related

Prevent React Google Maps from jumping to the center of the page when opening InfoWindow

When I click on the map icon and open the info window the page jumps to the center of my screen. How can i prevent the page from jumping when i open an info window?
const UserMarker = props => (
<Marker
position={props.location}
icon={props.icon}
onClick={() => props.users.setIsOpen()}
>
{props.users.isOpen && <InfoWindow onCloseClick={() => props.users.setIsOpen()}>
<div>
<h3 className="margin-bottom-1">{props.users.hasDescription ? <img alt={props.users.name} src={props.icon} /> : <i className="fa fa-user" />} {props.users.name}</h3>
{props.users.hasDescription ? <p>{props.users.description}</p> : ''}
<p>{props.users.hasDescription ? '' : `Bid: ${props.users.bidAmount && convertToDollars(props.users.bidAmount)}`}</p>
</div>
</InfoWindow>}
</Marker>
)
export const UserMap = withScriptjs(withGoogleMap((props) => {
const { users, area, zoom } = props;
const markers = users.map((user, idx) => <UserMarker
key={idx}
users={user}
location={{ lat: user.lat, lng: user.lon }}
icon={user.marker}
/>);
return (
<React.Fragment>
<GoogleMap
defaultZoom={zoom}
center={{ lat: area.lat, lng: area.lon }}
>
{markers}
</GoogleMap>
</React.Fragment>
);
}
))
I guess you mean info window auto pan, if so, this is the default behavior, to disable info window auto-pan on open set disableAutoPan property to true for InfoWindow component like this:
<InfoWindow options={{disableAutoPan: true}}>
<div>
content
</div>
</InfoWindow>
Here is a demo

Algolia - DateTimePicker - Select Date

I would like to implement a date timepicker with Algolia. If I choose a date, all elements should be displayed from this date.
Unfortunately, I have no idea how I can make this with Agolia.
I hope you can help me.
const datePicker = instantsearch.connectors.connectRange(
(options, isFirstRendering) => {
if (!isFirstRendering) return;
new Calendar({
element: $('.daterange--single'),
current_date: new Date(),
format: {input: 'DD.MM.YYYY'},
required: false,
callback: function() {
const start = new Date().getTime();
refine([start]);
},
});
}
);
search.addWidget(
datePicker({
attributeName: 'date',
})
);
<div class="daterange daterange--single"></div>
now i have a working code. Now a have the problem.. how i can change in my custom widget the searchParameters?
const search = instantsearch({
appId: '0000000',
apiKey: '000000000000',
indexName: 'Events',
routing: true,
searchParameters:{
filters: 'dateNumeric >= 1531591200'
}
});
var customWidget = {
init: function(options) {
$( "#datetimepickerNotime" ).focusout(function() {
var date = $('#datefromdatetimepicker').val();
var date = new Date (date);
alert("dateNumeric >= 1512752400");
});
}
};
search.addWidget(customWidget);
<div class='input-group date' id="datetimepickerNotime">
<input type='text' id="datefromdatetimepicker" name="date" class="form-control" autocomplete="off" value="<f:format.date date='now' format='d.m.Y' />"/>
<span class="input-group-addon">
<span class="fa fa-calendar"></span>
</span>
</div>
import { Formik, Field } from 'formik';
import { connectRange } from 'react-instantsearch-dom';
import * as Yup from 'yup';
const RangeFilter = ({ currentRefinement, min, max, refine }) => {
const validationSchema = Yup.object().shape({
minValue: Yup.number().min(min, `Minimum value must be at least ${min}`),
maxValue: Yup.number().max(max, `Maximum value must be at most ${max}`),
});
const onSubmit = (values) => {
refine({ min: values.minValue, max: values.maxValue });
};
return (
<Formik
onSubmit={onSubmit}
validationSchema={validationSchema}
initialValues={{
minValue: currentRefinement?.min,
maxValue: currentRefinement?.max,
}}>
{({ handleSubmit }) => (
<form onSubmit={handleSubmit}>
<Field name="minValue">
{({ field, form: { errors, touched } }) => (
<div>
<label htmlFor="price-min">To price:</label>
<input
className="input is-shadowless"
{...field}
id="price-min"
type="number"
placeholder="Min price"
/>
{errors.minValue && touched.minValue && (
<p className="help is-danger">{errors.minValue}</p>
)}
</div>
)}
</Field>
<Field name="maxValue">
{({ field, form: { errors, touched } }) => (
<div className="mt-2">
<label htmlFor="price-max">From price:</label>
<input
{...field}
id="price-max"
type="number"
className="input is-shadowless"
placeholder="Max price"
/>
{errors.maxValue && touched.maxValue && (
<p className="help is-danger">{errors.maxValue}</p>
)}
</div>
)}
</Field>
<button type="submit" className="ais-RefinementList-showMore mt-2">
Get Result
</button>
</form>
)}
</Formik>
);
};
export default connectRange(RangeFilter);

Vuejs toggle class in v-for

I'm making a list of items with v-for loop. I have some API data from server.
items: [
{
foo: 'something',
number: 1
},
{
foo: 'anything',
number: 2
}
]
and my template is:
<div v-for(item,index) in items #click=toggleActive>
{{ item.foo }}
{{ item.number }}
</div>
JS:
methods: {
toggleActive() {
//
}
}
How can i toggle active class with :class={active : something} ?
P.S I don't have boolean value in items
You can try to implement something like:
<div
v-for="(item, index) in items"
v-bind:key="item.id" // or alternativelly use `index`.
v-bind:class={'active': activeItem[item.id]}
#click="toggleActive(item)"
>
JS:
data: () => ({
activeItem: {},
}),
methods: {
toggleActive(item) {
if (this.activeItem[item.id]) {
this.removeActiveItem(item);
return;
}
this.addActiveItem(item);
},
addActiveItem(item) {
this.activeItem = Object.assign({},
this.activeItem,
[item.id]: item,
);
},
removeActiveItem(item) {
delete this.activeItem[item.id];
this.activeItem = Object.assign({}, this.activeItem);
},
}
I had the same issue and while it isn't easy to find a whole lot of useful information it is relatively simple to implement. I have a list of stores that map to a sort of tag cloud of clickable buttons. When one of them is clicked the "added" class is added to the link. The markup:
<div class="col-sm-10">
{{ store.name }}
</div>
And the associated script (TypeScript in this case). toggleAdd adds or removes the store id from selectedStoreIds and the class is updated automatically:
new Vue({
el: "#productPage",
data: {
stores: [] as StoreModel[],
selectedStoreIds: [] as string[],
},
methods: {
toggleAdd(store: StoreModel) {
let idx = this.selectedStoreIds.indexOf(store.id);
if (idx !== -1) {
this.selectedStoreIds.splice(idx, 1);
} else {
this.selectedStoreIds.push(store.id);
}
},
async mounted () {
this.stores = await this.getStores(); // ajax request to retrieve stores from server
}
});
Marlon Barcarol's answer helped a lot to resolve this for me.
It can be done in 2 steps.
1) Create v-for loop in parent component, like
<myComponent v-for="item in itemsList"/>
data() {
return {
itemsList: ['itemOne', 'itemTwo', 'itemThree']
}
}
2) Create child myComponent itself with all necessary logic
<div :class="someClass" #click="toggleClass"></div>
data(){
return {
someClass: "classOne"
}
},
methods: {
toggleClass() {
this.someClass = "classTwo";
}
}
This way all elements in v-for loop will have separate logic, not concerning sibling elements
I was working on a project and I had the same requirement, here is the code:
You can ignore CSS and pick the vue logic :)
new Vue({
el: '#app',
data: {
items: [{ title: 'Finance', isActive: false }, { title: 'Advertisement', isActive: false }, { title: 'Marketing', isActive: false }],
},
})
body{background:#161616}.p-wrap{color:#bdbdbd;width:320px;background:#161616;min-height:500px;border:1px solid #ccc;padding:15px}.angle-down svg{width:20px;height:20px}.p-card.is-open .angle-down svg{transform:rotate(180deg)}.c-card,.p-card{background:#2f2f2f;padding:10px;border-bottom:1px solid #666}.c-card{height:90px}.c-card:first-child,.p-card:first-child{border-radius:8px 8px 0 0}.c-card:first-child{margin-top:10px}.c-card:last-child,.p-card:last-child{border-radius:0 0 8px 8px;border-bottom:none}.p-title .avatar{background-color:#8d6e92;width:40px;height:40px;border-radius:50%}.p-card.is-open .p-title .avatar{width:20px;height:20px}.p-card.is-open{padding:20px 0;background-color:transparent}.p-card.is-open:first-child{padding:10px 0 20px}.p-card.is-open:last-child{padding:20px 0 0}.p-body{display:none}.p-card.is-open .p-body{display:block}.sec-title{font-size:12px;margin-bottom:10px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<div id="app" class="p-5">
<div class="p-wrap mx-auto">
<div class="sec-title">NEED TO ADD SECTION TITLE HERE</div>
<div>
<div v-for="(item, index) in items" v-bind:key="index" class="p-card" v-bind:class="{'is-open': item.isActive}"
v-on:click="item.isActive = !item.isActive">
<div class="row p-title align-items-center">
<div class="col-auto">
<div class="avatar"></div>
</div>
<div class="col pl-0">
<div class="title">{{item.title}}</div>
</div>
<div class="col-auto">
<div class="angle-down">
<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="angle-down" role="img"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"
class="svg-inline--fa fa-angle-down fa-w-10 fa-3x">
<path fill="currentColor"
d="M151.5 347.8L3.5 201c-4.7-4.7-4.7-12.3 0-17l19.8-19.8c4.7-4.7 12.3-4.7 17 0L160 282.7l119.7-118.5c4.7-4.7 12.3-4.7 17 0l19.8 19.8c4.7 4.7 4.7 12.3 0 17l-148 146.8c-4.7 4.7-12.3 4.7-17 0z"
class=""></path>
</svg>
</div>
</div>
</div>
<div class="p-body">
<div class="c-card"></div>
<div class="c-card"></div>
<div class="c-card"></div>
</div>
</div>
</div>
</div>
</div>

How to create a new DraftInlineStyle?

I have tried to create a new state with Modifier.insertText and the third argument is supposed to a draftInlineStyle
let ncs = Modifier.insertText(contentStates, selections, superscriptVar, ["BOLD"]);
This does give bold but when i try to change the style later on it doesn't change. I have figured out this is because draftInlineStyle is supposed to be a constructor. So how do I create a draftInlineStyle constructor if i am supposed to pass a draftInlineStyle constructor? or is there any other way to do this?
You should use OrderedSet.of from Immutable.js.
let ncs = Modifier.insertText(
contentStates,
selections,
superscriptVar,
OrderedSet.of('BOLD')
);
If you want to apply many styles, pass them as arguments: OrderedSet.of('BOLD', 'ITALIC')
Check the simplified demo in the hidden snippet below:
const {Editor, RichUtils, Modifier, SelectionState, EditorState} = Draft;
const { OrderedSet } = Immutable;
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {
editorState: EditorState.createEmpty()
};
}
insertTextHandler = (nameOfCustomStyle) => {
const currentSelection = this.state.editorState.getSelection();
const currentContent = this.state.editorState.getCurrentContent();
if (!currentSelection.isCollapsed()) return;
const newContentState = Modifier.insertText(currentContent, currentSelection, 'INSERTED TEXT', OrderedSet.of('BOLD'));
const newEditorState = EditorState.push(
this.state.editorState,
newContentState,
'change-inline-style'
);
this._handleChange(newEditorState)
}
toggleBoldStyle = () => {
this._handleChange(
RichUtils.toggleInlineStyle(
this.state.editorState,
'BOLD'
)
);
}
_handleChange = (editorState) => {
this.setState({ editorState });
}
render() {
return (
<div>
<div className="container-root">
<Editor
placeholder="Type away :)"
editorState={this.state.editorState}
onChange={this._handleChange}
/>
</div>
<button onClick={() => this.insertTextHandler()}>
INSERT TEXT
</button>
<button onClick={() => this.toggleBoldStyle()}>
TOGGLE BOLD STYLE FOR SELECTED TEXT
</button>
</div>
);
}
}
ReactDOM.render(<Container />, document.getElementById('react-root'))
body {
font-family: Helvetica, sans-serif;
}
.public-DraftEditor-content {
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.0/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/draft-js/0.7.0/Draft.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/draft-js/0.10.0/Draft.js"></script>
<div id="react-root"></div>

using durandal and knockout but I can't set span text from a drop down change

I'm trying to bind a value to a span tag by changing the position on the drop down.
My JS file code is
define(['plugins/router', 'durandal/app', 'knockout', 'durandal/system'], function (router, app, ko, system) {
var Property = function (ref, title) {
this.ref = ref;
this.title = title;
};
var propertyList = [
new Property("0", "sample"),
new Property("1", "sasasfa"),
new Property("2", "jgpjijo"),
new Property("3", "uifhiuefh")
];
var items = ko.observableArray(propertyList);
var selectedProperty = ko.observable();
return {
router: router,
items: items,
selectedProperty: selectedProperty,
activate: function () {
router.map([
{ route: '', moduleId: 'viewmodels/propertydetails', title: 'Property Details', nav: true } ]).buildNavigationModel();
return router.activate();
}
};
});
My html is:
<div>
<div class="header-nav-items">
<ul class="nav" data-bind="foreach: router.navigationModel">
<li data-bind="css: { 'header-tab-active': isActive }">
<a data-bind="attr: { href: hash }, html: title"></a>
</li>
</ul>
</div>
<div style="background-color: #E05000; padding: 3px; height: 25px;">
<div style="float: left; margin-left: 10px; color: #ffffff;">
<span id="title" data-bind="text: selectedProperty() ? selectedProperty().title : 'Unknown'"></span>
</div>
<div style="float: right; margin-right: 10px;">
<select id="PropertyDDL" data-bind="options: items, optionsText: 'title', optionsValue: 'ref', value: selectedProperty, optionsCaption: 'Please select a property'"></select>
</div>
</div>
I'm completely new to using Durandal and knockount. I'm trying to set the text of the span tag with the value title from PropertyList using selectedProperty().title but the value appears blank when I change the drop down to any position greater than 0. At pos 0 it displays unknown. If I replace selectedProperty().title with selectedProperty() then the ref prints out correctly on the span text. Any ideas?
All is much more simple. optionsValue: 'ref' means that selectedProperty() is 0, 1, 2 or 3.
Therefore selectedProperty().title is undefined and text is empty.
If you want to use selectedProperty().title just remove optionsValue: 'ref' from select.
Try encapsulating the text for your title span in a computed observable. Like this:
var self = this;
self.titleText = ko.computed(function() {
var prop = self.selectedProperty();
return prop ? prop.title : 'Unknown';
});
<span id="title" data-bind="text: titleText"></span>
Knockout can be a bit quirky when you execute the observable in the binding expression itself, it doesn't always register the dependency properly such that the binding is notified when the underlying selectedProperty observable changes (in my experience).