I try to fetch some API data and render on Client side. But I do not understand how should I proceed. I'm quite new to react. So I have been creating a React component which fetches api data but on render I do not have any list generated
on page load the api loads some initial data in form of nested object
than the component should parse this results child node which has about 10 elements
var Panel = ReactBootstrap.Panel;
var ProductBox = React.createClass({
getInitialState: function() {
return {
data: [],
products:[]
};
},
componentDidMount: function() {
$.get(this.props.source, function(result) {
var products = jQuery.parseJSON(result);
if (this.isMounted()) {
this.setState({
products:products.productItems.productItem
});
}
}.bind(this));
},
render: function() {
console.log(this.props.products);
return (
<div className="ProductBox">
<div>
<Panel header={this.state.products.name}>
<img className="img-responsive" src="{this.state.image}"/>
</Panel>
</div>
</div>
);
}
});
React.render(
<ProductBox source="/my/api" />,
document.getElementById('content')
);
You should realy not create a whole new component just for your ajax requests as you will have to rewrite/duplicate the component In every part of your application where there is ajax.
A better solution would be to create a module that handles get,post etc and then require it and using it from all over the application.
When you set the state, you are doing it wrong.
$.get(this.props.source, function(result) {
var products = jQuery.parseJSON(result);
if (this.isMounted()) {
this.setState({
products:productItems.productItem
});
}
}.bind(this));
productItems is not defined there. It should be products correct? Because you are doing var products = jQuery.parseJSON(result);.
Related
I've got a question regarding using Google's Invisible Recaptcha when using an AJAX form submission using Vue components.
I've created a VueJS component which I include in the following 'recaptcha button' component in:
<template>
<div>
<div v-if="failed" style="color: red;"><strong>Sorry, the captcha validation failed. Please try again.</strong></div>
<div :id="name"></div>
<button :class="classes" type="button" #click="validate()">
<slot>Submit</slot>
</button>
</div>
</template>
<script>
export default {
props: {
name: {
type: String,
default: 'recaptcha',
required: false
},
classes: {
type: String,
required: false,
default: ''
},
},
data: function ()
{
return {
failed: false,
};
},
mounted: function ()
{
this.initReCaptcha();
},
methods: {
initReCaptcha: function() {
var self = this;
setTimeout(function() {
if(typeof grecaptcha === 'undefined') {
self.initReCaptcha();
}
else {
grecaptcha.render(self.name, {
sitekey: 'site-key-here',
size: 'invisible',
badge: 'inline',
callback: self.response
});
}
}, 100);
},
validate: function ()
{
grecaptcha.execute();
},
response: function (token)
{
this.$parent.fields['g-recaptcha-response'] = token;
this.$parent.submit();
}
},
}
</script>
As you can see, I'm assigning Google's Recaptcha's callback function to the current instance of the recaptcha component's 'response' function. However, when I submit one of the forms, it seems to be calling the response function of the other component on the page.. and therefore trying to call submit on a form that has no input in so far..
We thought it might be a case of the recaptcha rendering not actually creating two instances and therefore on the second one, the callback is just being overwritten, but from logging the components in the mounted function, the form that's being submitted instead of the one we're trying to submit is being instantiated first, which lead us to believe it's not a case of overwriting...
Any help on the matter would be much appreciated!
Cheers,
PM
Figured this out, did not know that the render function returned the widget ID. grecaptcha.execute() will just execute the first widget in the global list if not given an optional widget ID parameter.
To tackle this, assign the widget ID returned by the render function to a data property in the component and then within the validate function, call execute with that widget ID as the parameter.
self.widgetId = grecaptcha.render(self.name, {...});
validate: function ()
{
grecaptcha.execute(this.widgetId);
},
I want to send a post request to Laravel backend using Vue.js. I'd like to make it without any extra library. I am making a pure Vue.http.get request and it works like a charm. For testing Laravel route and Controller returned data, I've made a ajax request in my template, which also works fine, returning the correct data. However, when I use Vue, via Vue.http.post('My/Controller/Route',data) it doesn't sends the post data to the Controller.
My Vue.js component:
<template>
<div class="opt-pro" v-for="r in profissionais">
<input :id="r.id" type="checkbox" :value="r.id" v-model="checkedNames" v-on:change="filterResources()"/><label> {{ r.title }}</label>
</div>
</template>
<script>
export default {
data() {
return {
dados: {view: 'dia', pro: [], data: 'Setembro 11, 2017'},
meus_recursos: [],
profissionais: [],
checkedNames: []
}
},
methods:{
getResources: function() {
var self = this;
return Vue.http.get('/admin/getResources').then((response) => {
_.forEach(response.data.resources,function(item){
self.meus_recursos.push(item);
self.profissionais.push(item);
});
console.log(self.meus_recursos);
});
},
filterResources: function(){
this.dados.pro = this.checkedNames; // returned by another Vue piece of code - console.log() returns the correct data for this var
return Vue.http.post('/admin/getAgendamentosPorProfissional', this.dados).then(
(response) => {
console.log(response.body);
},
(response) => {
console.log("Error");
console.log(response);
console.log(response.body);
});
}
}
My Laravel Controller function:
public function getAgendamentosPorProfissional(){
// $view = $_POST['view'];
// $pro = $_POST['pro'];
// $data = $_POST['data'];
$post = $_POST;
return response()->json(array('post' => $post),200);
}
It returns in my console:
{post: Array(0)}
My jQuery AJAX function:
$.ajax({
type:'POST',
url:'/admin/getAgendamentosPorProfissional',
data: {"data": data, "view": view, "pro": [pro],"_token": "{{ csrf_token() }}"},
success:function(data){
console.log("AJAX - /admin/getAgendamentosPorProfissional");
console.log(data);
}
});
It returns in my console:
post:
data: "Setembro 11, 2017",
pro:["75"]
view:"dia"
_token:"6LviacS2KoBqjXxTsFhnTtAQePuEzZ49OMwqBmbM"
It's not a CORS issue, since it returns the correct data from the requested url in laravel. How can I fix this?
My token is set at laravel/resources/assets/js/bootstrap.js file:
window.Vue = require('vue');
require('vue-resource');
Vue.http.interceptors.push((request, next) => {
request.headers.set('X-CSRF-TOKEN', Laravel.csrfToken);
next();
});
please find vuejs code below. When i access the url directly on the browser, the data(JSON) are retrieved but when retrieving the data by the http request, the data are not stored in the variable. I am using Vuejs and Laravel. Can someone tell me what is wrong with the code. Thank you.
<script>
Vue.component('account-type-list', {
template: `<div></div>`
data:() => {
return {
typesofaccount:[]
};
},
created: function() {
this.getAccountTypes();
},
methods: {
getAccountTypes: function() {
this.$http.get('/list/accounttypes').then(response => {
this.typesofaccount = response.body
});
},
}
});
Vue.component('type', {
template: '<a class="active item"><slot></slot></a>'
});
new Vue({
el: '#root',
});
</script>
this inside the response callback is likely not your component.
Try:
getAccountTypes: function() {
var component = this;
this.$http.get('/list/accounttypes').then(response => {
component.typesofaccount = response.body
});
},
Had to import
<script src="https://unpkg.com/vue"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-resource#1.3.4"></script>
in the child blade template not in the main layout.
I am trying to use ko.mapping to transform data to a viewmodel. The result come from an async call to a web service.
Simple view:
<div data-bind="with: myData">
<div data-bind="text: mapWidth"></div>
<div data-bind="text: mapHeight"></div>
<div data-bind="foreach: priceRanges">
<div data-bind="text: title"></div>
</div>
AND the view model is as follows:
var ViewModel = function() {
var self = this;
self.myData = null;
var data = {
action: 'GetPricePoints',
type: 'who cares'
};
$.ajax({
url: 'http://cdt.lotamore.com/api/imap',
data: { "": JSON.stringify(data) },
//async: false, // works!
async: true, // doesn't work!!!!!
type: 'post'
})
.done(function (data) {
self.myData = ko.mapping.fromJS(data);
})
.error(function (data) {
alertError(data);
})
.always(function () {
});
};
When I run this synchronously is works fine. However, when I run it asynchronously it doesn't update the myData within my view model.
I have created a fiddle here:
http://jsfiddle.net/jgergen/jF9pm/20/
I really don't want to make ajax calls that block the UI thread!
What am I doing wrong here?
Thanks,
Jim
Here is the solution:
I have changed the line:
self.myData = null;
to:
self.myData = ko.observable();
This is not all, I tried this before without favorable results. In addition to making myData observable, I had to change the way it is updated. Here is the new .done method:
.done(function (d) {
self.myData(ko.mapping.fromJS(d));
})
So, what I needed to do is treat this field as I would any other observable.
You can see it here at this new fiddle: http://jsfiddle.net/jgergen/jF9pm/47/
I hope that this helps more than me. I searched for a solution to this problem all over the web without any results. So here it is.
Thanks,
Jim
I have built a model from GET request and display the content that I need into a form, mainly dropdown options. User then completes the form and 'POST' back to the api. The API that I am using isn't formatted in a way that I can use for ember-data so I have opted to render my model with Ember.Object
var Prequalification = Ember.Object.extend();
Prequalification.reopenClass({
template: function(){
return Ember.$.ajax({
url: "/prequalification",
dataType: 'json'
}).then(function(response){
var template = response.collection.template.data;
return template;
});
}
});
export default Prequalification;
My controller decorates the view:
var IndexController = Ember.ArrayController.extend({
businessType: function(){
var content = this.get('content');
console.log(this);
return content.get(10);
}.property('content'),
loanType: function(){
var content = this.get('content');
return content.get(5);
}.property('content')
});
export default IndexController;
So on form submit, what are my options for Posting back to the API?
Thanks!
Use an action and associate it with a button.
actions: {
save: function(){
alert('ajax save here');
}
}
http://emberjs.jsbin.com/jositowa/1/edit