I receive data in a function and this function needs to load a new page. I was doing this with Jquery using the method .load(), But my vue method gets an error saying that can not find the element in the other page.I believe that could be a better approach, but I do not know how I can pass data through a vue component
static foo(a,b){
$('#maindiv').load("/newPage");
new Vue({
el: '#newPageElem',
data: {
vueVar1:a
vueVar2:b
},
});
}
How can I do that? I believe that using Jquery is not the best way to achieve this, but I dont know how to change routes with vue and passing parameter between them.
Thanks.
You can take a look at vue-router here: http://router.vuejs.org/en/essentials/getting-started.html - it allows you to handle all the client-side routes.
For making http calls to receive data from server, you can use vue-resource (https://github.com/vuejs/vue-resource)
It is better to avoid mixing jQuery with Vue, as Vue is responsible for rendering the DOM. If you make any DOM changes with jQuery, it will get over-written by Vue in the next DOM update. So you will end up spending a lot of time in debugging.
Also, you cannot instantiate a Vue app inside a function, as seen in your code example, unless you call the function on page load. Ideally, the first few lines of script should start the Vue app.
Related
In general, I want to update some state and show a new component (menu with options) above the microphone button when the microphone is being hovered, but I don’t know how to easily access this MicrophoneButton component.
Right now I use hacky vanilla JS approach with document.querySelector, because with it I do not need to rewrite anything inside botframework-webchat library just to get access to MicrophoneButton component, because as far as I understand to get access to it using proper React I would have to use refs and/or forwardRefs, but I don’t think it’s possible without rewriting the code for MicrophoneButton component.
I would like to do something like this but without resorting to vanilla JS in my React app:
useEffect(() => {
let mic = document.querySelector('div.webchat__microphone-button');
if (mic) {
mic.addEventListener('mouseenter', () => {
setMicIsHovered(true);
})
mic.addEventListener('mouseleave', () => {
setMicIsHovered(false);
})
}
}, [showMic])
I’m a beginner in React world so it’s very likely that I’m missing something here and there is an easy way to do it without explicitly using event listeners, so I would really appreciate some guidance.
I am complete noob to react so please bear with me.
I am creating a webpage that has dusting on react components on it. I am not creating the whole page using react and this isn't an option.
What i want I want to do is load a json file and use the data to set the properties of the components on the page. These properties won't be changing once the page has rendered.
I have managed to load the json and set the properties of a component. I also need to reuse some of the properties of this component in other components that are not a children of the first component.
I suppose very basically I need to create a global set of data that can be used by any component on the page. I'm coming from an angular background so maybe this is throwing me off course a bit
Here is what I have so far
var ReleaseList=React.createClass({
getInitialState: function(){
return {
allReleases:[]
}
},
showResults :function(ReleaseData){
this.setState({
allReleases :ReleaseData
});
},
getReleases:function(){
fetch('http://imac.local:5757/s0dj8a.json').then(function(response) {
// Convert to JSON
return response.json();
}).then(function(j) {
var ReleaseData=j.releaseDetail[0]
this.showResults(ReleaseData)
}.bind(this));
},
componentDidMount(){
this.getReleases();
},
render:function(){
return (
<h1>{this.state.allReleases.title}</h1>
)
}
});
var ReleaseDataTitle=React.createClass({
render:function(){
return (
<div>
<h2>{this.props.title}</h2>
// This needs to be the same as this.state.allReleases.title in the previous component
</div>
)
}
});
ReactDOM.render(<ReleaseList/>, document.getElementById('content'));
ReactDOM.render(<ReleaseDataTitle title={'I need this to be the same as this.state.allReleases.title in <ReleaseList />'}/>, document.getElementById('banner'));
I wouldn't consider React to render small static parts of your website just as I wouldn't use jQuery if I know JS well - it's unnecessary download for such a simple task. I would however consider Preact, a 3kb React clone that was made for these kind of situations: small parts of site / app with similar API.
But here's how I would do it with React (I imagine Preact is very similar).
These properties won't be changing once the page has rendered.
If the data doesn't change, you don't even need to store the data to global variable, just render React components while passing the fetched data as props.
fetch('http://imac.local:5757/s0dj8a.json').then(function(response) {
return response.json()
}).then(function(data) {
ReactDOM.render(<First data={data} />, document.getElementById('first'))
ReactDOM.render(<Second data={data} />, document.getElementById('second'))
// And any other React component you wish to add to DOM
})
Now the data is available in each of these components as this.props.data. Now you can do whatever you want with this data: format, change, pass to children, render etc.
PS! Me and even React creators recommend to use ES6 classes, especially if you just started ..
The key is something you've already mentioned in your question. You need a global state where you can store the data required by your components. You will also need some methods to do the data distribution.
For the sake of easy maintenance, predictability and reliability of our apps, I believe React components should be agnostic about data (which means they should only represent the View layer, and shouldn't handle API calls or data processing by themselves).
Since your website is not completely built with react, you can delegate vanilla javascript methods for data fetch and pass it as a props to your React components. If you ever plan to fully migrate to React, you can make use of Redux, MobX, etc. to maintain your global state.
When I google "Knockout Google Maps" I find quite some KO-based Google Maps implementations. All of which I was able to find take the approach to use a custom binding handler whereas I originally intended to implement it as a Knockout component.
Examples:
http://www.codeproject.com/Articles/351298/KnockoutJS-and-Google-Maps-binding
http://www.hoonzis.com/knockoutjs-and-google-maps-binding/
https://github.com/manuel-guilbault/knockout.google.maps
Can anyone point me in the right direction why one would prefer a custom binding handler over a KO component here?
My planned use case is this:
I'm implementing a page with a list of address search results. The list so far is a KO component, each list entry is generated by another KO component which the list component repeatedly calls in a foreach binding. Next to this list of search results I need a google map showing the result entries also in the map. There will also be quite a lot of interaction between the list, the list entries and the map.
Here's what I've got so far:
var GMap = function () {
var self = this;
var initMap = function() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 13,
center: {lat: 51.4387974, lng: 6.9922915}
});
};
initMap();
};
$(document).ready(function() {
ko.components.register('gmap', {
viewModel: GMap,
template: { element: 'gmap' }
});
ko.applyBindings();
});
#map {
height: 400px;
width: 600px;
}
<script src="https://maps.googleapis.com/maps/api/js?v=3.22"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<gmap></gmap>
<template id="gmap">
<div id="map"></div>
</template>
A component and a custom handler are completely different things.
Custom binding
Basically a custom binding have access to:
the HTML component where it's used
the bound value (expression supplied to the binding)
all the other bindings in the element
the binding context of the element, from which you can acces to $root, $parent, and so on
Its definition includes two functions:
init: that allows to do the initial setup, like initializing widgets, setting event handlers and so on
update: it's called after init. In that moment you can access properties (including observable properties) through the binding, all the element bindings, the context and so on. This creates subscriptios that will call update when any of the accessed observable changes.
So a custom binding shuld be used when you need to interact directly with the DOM element, for example to modify its properties, initialize widgets, subscribe to events and so on
Component
A component is completely different. When you define a componente you must define:
a template, which is a set of DOM elements, usually with bindings
a viewmodel (usually a constructor or a factory)
When you use the component:
the viewmodel is instanced
the template is loaded
the viewmodel is bound to the template
So, a componente allows to reuse viewmodels and templates
So, what's the difference?
A custom binding has direct access to the DOM elements, allowing to interact with them, subscribe to events, modify properties, and so on
A component is only a viewmodel, and a set of DOM elements with bindings to that particular viewmodel.
So, in the case of Google Maps, which needs to initialize a widget (the map) and interact with Map events, and respond to observable propèrties cahnges, you could never use a component, because the component doesn't allow the direct interaction with the DOM elements. (Remember is a bunch of HTML elements with bindings, and the corrresponding view model, whic can't include any logic to intercat with those elements).
A custom binding usually applies to a single element (althoug it could handle its children, like foreach). In the case of Google Maps you only need the element in which you'll show the map.
A component is usually a more or less complex set of DOM elements, which are not accesible "from the outside". The only communication with the main viewmodel is done through parameters. The component cannot directly interact with the DOM elements: it must do it via ko bindings.
So, for the case of Google Maps is clear that you need a custom binding.
It only makes sense to create a component when you want to modularize or reuse a set of DOM elements, and the related viewmodel, which can also include functionality like accessing web services (via AJAX), making computations (propbaly by using computed observables), and so on. For example, a shopping cart could be implemented using a component, which would include:
the DOM elements to show the items in the cart (probably an HTML table, and some controls)
controls to modify the cart content (for example for deleting elements, or changing quantities)
a viewmodel that show the total, the taxes and so on
functionality to store the cart for later, or pay for it (which could be ajax calls to services)
In this case the cart would have a viewmodel which would include the computed observables (to show the total and taxes), the functionality to remove items, or modify quantities, or store or pay, and so on. And a concrete set of DOM elements with bindings for this viewmodel, i.e. the HTML to show the cart and interact with it.
In the case of Google Maps a component could not be used without the help of a custom binding or with the hacky use of additional, non ko, scripts.
If you wanted to show a list of places beside a map, and modify that list, you could use a component, which would include a viewmodel with the list and related functionality, and a template including an element with the Google Maps custom binding. That would make sense: viewmodel + several elements.
Conclusion
This all means that a custom binding usually have a deep interaction with the bound DOM element, while a component has a higher level interaction with the elements, which must be done through bindings.
So, they play a role at a very different level. You cannot compare or interchange them.
If you insist on doing so, you could create a beast of a binding which behaves like a component, becasue you have full control on the elements, and full acces to the view model, but that's harder to implement than a component. And probably could do the other way round also in some esoteric way.
Binding
Binding, a custom or not, is a very simple concept that covers 2 things:
A property of a UI element changes, and thus it should update an object (ViewModel)
A property of the object (ViewModel) changes, and thus it should update the UI element.
From the above if only 1 implemented, it is called One Way Binding (because if you change the UI, it will update the object but not the other way around). If both 1 and 2 are implemented, it is called Two Way Binding.
So at any time if you think you need something to do that, you would need to use binding, custom binding if the framework does not have the binding you need.
Most likely, the maps you speak of needed something like above. And it actually did because the author says this in the first paragraph:
Concretely, you can learn how to make the maps marker part of the View and automatically change its position any time when the ViewModel behind changes.
See, the author talks about 2 above: When the ViewModel changes, change the position of UI element.
Component
A component is a concept of having a reusable item that may have a UI but not necessarily, and all the code needed to make it work packaged along with it. This way it can be reused. For example, it may simply be an input UI element that only allows numbers. All the code needed for it is packaged along with the UI element.
Now the code packaged along with it may code related to bindings. It may even have custom bindings if the framework they used did not have the binding they needed. In addition it may have additional code that has nothing to do with binding.
Furthermore, a component may have a single UI element or multiple. A good example of a component with multiple elements would be a message box.
In Conclusion
Bindings and Components are separate things. A component may have bindings within it or it may have other code to make it work or both.
In the case of the maps you speak of, they have only added a feature to it: To react to changes in the ViewModel. It is not a component because it is not self contained and reusable.
They could have done it using a component. However, if they did that and said it is a KO component, it may still have KO specific binding code packaged with it along with the ViewModel and all the UI elements needed.
I'm a little stumped on this one. I defined a route called classes/:id. When navigating to that route in the app, the componentDidMount() is called. However, when reloading the page or copying and pasting the URL the page completely loads, but the componentDidMount() method is not called at all.
From what I have read, the reason is because the same component mounted even though the page is being reloaded which is why the lifecycle method does ever get fired off.
What are some ways to handle this? Your help is greatly appreciated. Thanks!
componentDidMount will not be called again if you are already at a classes/:id route. You'll probably want to do something along the lines of:
componentDidUpdate(prevProps) {
if (this.props.id !== prevProps.id) {
// fetch or other component tasks necessary for rendering
}
}
I try to avoid any mixins (see willTransitionTo), as they are considered harmful.
Although componentDidMount does not fire when changing routes for the same component, componentWillUpdate and componentWillReceiveProps do.
From there, you can detect parameter changes, and can fire your actions accordingly.
the componentWillReceiveProps,componentDidUpdate lifecycle will receive the new props and then setState to change state to trigger render method.
I just dealt with this exact issue, took me a while to figure out the problem. I'm sure everything previously suggested works great as a solution. How I solved the problem was a bit different though. My componentDidMount function was essentially just providing a state update, so I just moved the functionality directly into the state and bypassed componentDidMount.
Honestly, I'm not sure if this is best practice or not (very happy for feedback if it isn't), but it's running efficiently and works great so far.
I have an array from ajax and i need to create jQuery Mobile Listview. I don't found a method for this, so is it possible?
Here's a working example: http://jsfiddle.net/Gajotres/SS7vJ/
And another example with an array: http://jsfiddle.net/Gajotres/yHHWQ/
$(document).on('pagebeforeshow', '#index', function(){
$('<ul>').attr({'id':'test-listview','data-role':'listview', 'data-filter':'true','data-filter-placeholder':'Search...'}).appendTo('#index [data-role="content"]');
$('<li>').append('Audi').appendTo('#test-listview');
$('<li>').append('Mercedes').appendTo('#test-listview');
$('<li>').append('Opel').appendTo('#test-listview');
$('#test-listview').listview().listview('refresh');
});
Also don't forget to call .listview( twice, first without refresh parameter, and second time with a refresh parameter. Without it you will receive this error:
cannot call methods on listview prior to initialization
If you want to find out more about how jQuery mobile handles dynamically added content and its markup take a look at this ARTICLE, to be transparent it is my personal blog, or find it HERE.