How to display list? - javascript

How correctly to display the list received through URL in JSON?
Here is an example of a project. If I use a local variable - everything works, if I get the list, it displays an error.
constructor(props) {
super(props);
this.urlNews = "https://api.myjson.com/bins/1nrbo";
this.state = {
news: "",
links: [
{
name: "Имя 1",
url: "http://localhost:1",
use: true
},
{
name: "Имя 2",
url: "http://localhost:2",
use: false
},
{
name: "Имя 3",
url: "http://localhost:3",
use: false
}
]
};
}
getNews() {
fetch(this.urlNews)
.then(response => {
return response.json();
})
.then(json => {
this.setState({
news: json
});
console.log(this.state.news[1]);
});
}
componentDidMount() {
this.getNews();
}
render() {
const { news } = this.state;
return (
<ul>
{news.map((item, index) => <li>1</li>)}
</ul>
);
}
How right?

Because you defined initial value of news as string, define it as an array.
Write it like this:
this.state = {
news: [],
....
fetch will be a asynchronous call and you are fetching in componentDidMount that will get called after initial rendering, so before you get the response, you are trying to use map on string and that is throwing the error.
Check this snippet:
let news = '';
news.map(el => {
console.log(el);
})

You are not using map properly. map does not support object literal. Need to supply it with an array. You need to define the sate as an array and use the following render function.
this.state = {
news: [],
links: [
{
name: "Имя 1",
url: "http://localhost:1",
use: true
},
{
name: "Имя 2",
url: "http://localhost:2",
use: false
},
{
name: "Имя 3",
url: "http://localhost:3",
use: false
}
]
};
The following render function works.
render() {
return (
<ul>
{this.state.news.map(() => <li>1</li>)}
</ul>
);
}

Related

Convert api response array to another array to pass to Vue prop

I want to use this vue flipbook component and it needs a array of image urls for the prop "pages". My posts response is coming from the wordpress rest api.
I need to get the "image" property from the response array and convert it into another array of image urls. Normally I would use the posts() in computed like v-for=post in posts in my template and display the image like post.image_full in the loop..
Flipbook component:
<Flipbook
class="flipbook"
:pages="imagesArray" <--- images array here
v-slot="flipbook"
ref="flipbook"
>
</Flipbook>
My Posts.vue component:
export default {
name: 'GridOne',
props: {
page: {
type: Number,
required: true
}
},
data() {
return {
request: {
type: 'posts',
params: {
per_page: this.$store.state.site.posts_per_page,
page: this.page
},
showLoading: true
},
totalPages: 0
}
},
computed: {
posts() {
return this.$store.getters.requestedItems(this.request) <--- my response array
}
},
methods: {
getPosts() {
return this.$store.dispatch('getItems', this.request)
},
setTotalPages() {
this.totalPages = this.$store.getters.totalPages(this.request)
}
},
created() {
this.getPosts().then(() => this.setTotalPages())
}
}
You can use JavaScript "map" function. This function takes one array and return a new one.
// If this is the response array....
const response = [{name: 'image 1', url: 'https://uri.com/img1'}, ...]
// Then you return something like this
response.map(item => {
return {
...item,
image_full: item.url
}
})

Determining pr eliminating empty key:value from an object for multiple filtering purposes

My app has a feature where users can filter results based on "blood group" and "city", and areas. Results will be retrieved from DB using Axios for Vuejs through "URL" query strings. Example url is: http://example.com/api/results?blood=a+&city=london
It should work in a way that when a user select just blood group from select menu: the url would exclude the city parameter. But from my current code, I can't get it stripped of, as a result, the database query returns no results on the basis that cityreturns null value.
Here's what I have in my Vue component:
<script>
export default {
props: ['user'],
data() {
return {
auth_user: this.user,
results: {},
blood_groups: "",
cities: "",
districts: "",
areas: "",
donorUrl: "/api/donors",
requestedBlood: "",
requestedCity: "",
requestedDist: "",
requestedArea: "",
params: {}
};
},
created() {
this.fetchDonors();
this.fetchCities();
},
methods: {
fetchDonors() {
let url = "/api/donors";
axios.get(url).then(response => {
this.results = response.data.data;
this.blood_groups = [...new Set(response.data.data.map(x=> x.blood_group))];
});
},
fetchCities() {
let url = "/api/location_type/cities";
axios.get(url).then(response => {
this.cities = response.data.cities
})
},
selected_blood_group(event) {
this.requestedBlood = event.target.value;
this.get();
},
get_city(event) {
this.requestedCity = event.target.value;
this.get();
},
get() {
let request = {
params: {
blood: this.requestedBlood,
city: this.requestedCity,
dist: this.requestedDist,
area: this.requestedArea
}
}
axios.get('/api/donors', request).then(response => {
this.results = response.data.data
})
}
},
};
</script>
My query is how can I remove or check if any of the following properties contains empty value, so that I do not include them in axios params?
let request = {
params: {
blood: this.requestedBlood,
city: this.requestedCity,
dist: this.requestedDist,
area: this.requestedArea
}
}
You can try below code.
Create a new object(called testParams) and add that object in params.suppose requestedCity is selected(not only but any variable is selected ). Then you can do like below.
if(requestedCity.length!=0)
{
testParams["city"]=requestedCity; // OTHERWISE DON'T ADD IN testParams object
}
Finally while making request through axios add testParams in params object like below.
axios.get('/yourUrl/',{
params:{
testParams //here vue will automatically sets 'testParams':testParams
}
})
I got it working with the following approach:
let request = {
blood: this.requestedBlood,
city: this.requestedCity,
dist: this.requestedDist,
area: this.requestedArea
}
for(let k in request)
if(!request[k]) delete request[k];
axios.get('/api/donors', {
params: request
}).then(response => {
this.results = response.data.data
})

Vue v-for on first item containing property X call a method

Let's say I have a component which repeats with a v-for loop like so:
<hotel v-for="(hotel, index) in hotels"></hotel>
And my hotels array would look like so:
[
{
name: false
},
{
name: false
},
{
name: true
},
{
name: true
}
]
How could I perform an action when my v-for loop encounters the property name set to true only on the very first time it encounters this truthy property?
I know I could probably cache a property somewhere and only run something once and not run again if it has been set but this does not feel efficient.
Use a computed to make a copy of hotels where the first one has an isFirst property.
computed: {
hotelsWithFirstMarked() {
var result = this.hotels.slice();
var first = result.find(x => x.name);
if (first) {
first.isFirst = true;
}
return result;
}
}
Just use computed source
HTML
<div v-for="(hotel, index) in renderHotels"></div>
JS
export default {
name: 'message',
data () {
return{
hotels:[
{
name: false
},
{
name: false
},
{
name: true
},
{
name: true
}
] ,
wasFirst : false
}
},
methods:{
},
computed:{
renderHotels(){
return this.hotels.map((hotel)=>{
if(hotel.name && !this.wasFirst){
this.wasFirst = true;
alert('First True');
console.log(hotel);
}
})
}
}
}
Best way is to use filter function.
data() {
return {
firstTime: false,
};
},
filters: {
myFunc: function (hotel) {
if (hotel.name && !this.firstTime) {
//perform some action
this.firstTime = true;
}
}
}
<hotel v-for="(hotel, index) in hotels | myFunc"></hotel>

React map nested array within object

The goal is to pull in the nested array "records". My current output displays the array within the react console, but with an error. I will try and be as concise as possible but will keep things short.
The error screen has 3 lines that are referencing _getRecords so im positive that _getRecords is the problem child.
class RecordBox extends Component {
constructor() {
super();
this.state = {
showComments: false,
results: []
};
}
render(){
const records = this._getRecords();
return (
// jsx template code...
);
}
// API Call
_fetchRecords() {
$.ajax({
method: 'GET',
url: 'http://apidata:8888/data.json',
success: (results) => {
this.setState({ results });
},
error: () => {
console.log('error');
}
});
}
_getRecords() {
// TypeError: this.state.results.map is not a function...
return this.state.results.map((record) => {
return <Comment body={record["Contractor Name"]} />
});
}
}
I have a feed that looks like the below. I do not have permission to modify this.
{
"result": {
"records": [
{
"id": 1,
"email": "clu.hey#gmail.com",
"author": "Clu",
"Contractor Name": "Just say no to love!!",
"avatarUrl": "https://placeimg.com/200/240/any"
},{
"id": 2,
"email": "hello#gmail.com",
"author": "Anne Droid",
"Contractor Name": "I wanna know what love is...",
"avatarUrl": "https://placeimg.com/200/240/any"
}
]
}
}
I think you just aren't setting the state to the right thing. Your state.results is currently an object. Just make sure when you set your state, you set state.results to results.result.records
this.setState({ results: results.result.records })
One thing you could also do is map the results directly in the jsx code and skip using the _getRecords function.
<div>
{
this.state.results.map( ( record ) => {
return <Comment />
}
}
</div>
This is the way I usually write this as it's easier for me to read, but it's personal preference.
I hope this helps!
The _fetchRecords function needs to change to:-
_fetchRecords() {
$.ajax({
method: 'GET',
url: 'http://apidata:8888/data.json',
success: (results) => {
this.setState({ results: results.result.records });
},
error: () => {
console.log('error');
}
});
}

Changing state in store vue js

I am having issues setting a variable via ajax.
const store = new Vuex.Store({
state: {
conversationsList: []
},
mutations: {
conversationList(state, payload) {
state.conversationList = payload;
}
}
});
setInterval(function () {
axios.get('/conversation/get-conversations')
.then((response) => {
store.commit('conversationList', response.data);
});
}, 1000);
I cant understand why the state.conversationList = payload does not change the value?
Even replacing the ajax call with a simple array assignment such as
var testList = [
{id: 1, author: 'john', type: 'follower', lastMessage : 'hi'}
];
store.commit('conversationList', testList);
doesnt work

Categories