Ionic 4 unable to display data inside ngFor - ionic4

I am trying to fetch payment methods from razorpay payment gateway. But unable to display it. The problem is there is no data available at the time of display. How do I wait for data to load?
Thank you in advance
.ts
banks : [];
constructor() {
this.razorpay = new Razorpay({
key : 'XXXXXXXXXXX',
key_secret: 'XXXXXXXX'
})
this.razorpay.once('ready', function(response) {
this.banks = response.methods.netbanking
console.log(this.banks)
this.display = true
})
}
html
<ul *ngIf="display">
<li *ngFor="let hero of banks | async">
{{ hero }}
</li>
</ul>

As your result console.log(this.banks) is in key value pair.
Your keys are AUBL,ABPB,AIRP,ALLA
You can bind data like this
<ul *ngIf="display">
<li *ngFor="let hero of banks | async">
{{ hero.AUBL }}
{{hero.ABPB}}
//so on
</li>
</ul>

It seems like the API returns Object rather that an Iterable such as Array.
if you need to display each property of such object you would have to transform the object to an array:
constructor() {
this.banks = [];
this.razorpay = new Razorpay({
key : 'XXXXXXXXXXX',
key_secret: 'XXXXXXXX'
})
this.razorpay.once('ready', (response) => {
let methodsObj = response.methods.netbanking
this.banks = Object.entries(methodsObj)
console.log(this.banks)
})
}
Then your template is:
<ul>
<li *ngFor="let hero of banks">
{{ hero[0] }}, {{ hero[1] }}
</li>
</ul>

With the KeyValuePipe you will be able to iterate over the properties of the object. Remove the async pipe, as you're not working with an observable.
<ul *ngIf="display">
<li *ngFor="let hero of banks | keyvalue">
{{ hero.key }}: {{ hero.value }}
</li>
</ul>
And initialize the banks object correctly as an object instead of an array.
banks = {};
This will give a result like
AUBL: AU Small Finance Bank
ABPB: Aditya Birla Idea Payments Bank
...

this.razorpay.once('ready', (response) => {
this.banks = response.methods.netbanking
console.log(this.banks)
this.display= true
console.log(this.display)
})
I have to use arrow (response) => as a callback. By using function() you can't bind object data

Related

I almost have a page numbering with comments but something fails with mounted (vue.js)

Here you have the HTML:
<div>
<nav>
<ul class="pagination">
<li #click.prevent="paginaAnterior">Anterior</li>
<li #click.prevent="contenidoPagina(pagina)" v-for="pagina in totalPaginas()" class="page-item">{{ pagina }}</li>
<li #click.prevent="paginaSiguiente">Siguiente</li>
</ul>
</nav>
<article class="caja__articulo-noticias" v-for="item in datosPaginados">
<p>
{{ item.nombre }} {{ item.fields.Nombre }} {{ item.apellido }} {{ item.fields.Apellidos }}
</p>
<p>
{{ item.comentario }} {{ item.fields.Comentario }}
</p>
</article>
</div>
And this is the vue.js. I would like to show the first page of the comments when the website is loaded
mounted: function () {
this.obtenerDatosNoticia2();
**this.contenidoPagina(1);** // it doesn´t shows me the first page
},
methods: {
totalPaginas: function () {
return Math.ceil(this.infosNoticia2.length / this.elementosPorPagina);
},
contenidoPagina: function(numeroPagina){
this.paginaActual = numeroPagina;
this.datosPaginados = [];
let inicio = (numeroPagina * this.elementosPorPagina) - this.elementosPorPagina;
let fin = (numeroPagina * this.elementosPorPagina);
this.datosPaginados = this.infosNoticia2.slice(inicio,fin);
},
paginaAnterior: function () {
if(this.paginaActual > 1) {
this.paginaActual = this.paginaActual - 1;
}
this.contenidoPagina(this.paginaActual);
},
paginaSiguiente: function () {
if(this.paginaActual < this.totalPaginas()) {
this.paginaActual = this.paginaActual + 1;
}
this.contenidoPagina(this.paginaActual);
}
}
})
To put you in context I'm doing a blog about music. I have a section with news about music, singers... and at the bottom I've made a kind of number pagination to list all the comments that people can add. The number pagination works right, the problem is that I'd like to see the first page of the comments when you're in this section because I only see the number pagination (1, 2, 3, 4...) and you've to click in each one to see the comments.

Vue.js Autocomplete

I am building a live search component with Vuejs. The search is working as expected. On keyup the method populates an unordered list. I am at a loss but need to:
Click on a selection from the search results and populate the input with that name.
Get the selected id.
Any suggestions?
The View
<label>Vendor:</label>
<input type="text" v-model="vendor" v-on:keyup="get_vendors">
<div class="panel-footer" v-if="vendors.length">
<ul class="list-group">
<li class="list-group-item for="vendor in vendors">
{{ vendor.vendor_name }}
</li>
</ul>
</div>
The Script
export default {
data: function() {
return {
vendor:'',
vendors: []
}
},
methods: {
get_vendors(){
this.vendors = [];
if(this.vendor.length > 0){
axios.get('search_vendors',{params: {vendor: this.vendor}}).then(response =>
{
this.vendors = response.data;
});
}
}
}
}
</script>
The Route
Route::get('search_vendors', 'vendorController#search_vendors');
The Controller
public function search_vendors(Request $request){
$vendors = vendor::where('vendor_name','LIKE','%'.$request->vendor.'%')->get();
return response()->json($vendors);
}
This is what I came up with. Works nicely.
The View
<label>Vendor:</label>
<input type="text" v-model="vendor" v-on:keyup="get_vendors" class="col-xl-6 form-control ">
<div class="panel-footer autocomplete-box col-xl-6">
<ul class="list-group">
<li v-for="(vendor,id) in vendors" #click="select_vendor(vendor)" class="list-group-item autocomplete-box-li">
{{ vendor.vendor_name }}
</li>
</ul>
</div>
The Script
export default {
data: function() {
return {
vendor:'',
vendor_id:'',
vendors: []
}
},
methods: {
select_vendor(vendor){
this.vendor = vendor.vendor_name
this.vendor_id = vendor.id
this.vendors = [];
},
get_vendors(){
if(this.vendor.length == 0){
this.vendors = [];
}
if(this.vendor.length > 0){
axios.get('search_vendors',{params: {vendor: this.vendor}}).then(response => {
this.vendors = response.data;
});
}
},
},
}
</script>
The Route
Route::get('search_vendors', 'vendorController#search_vendors');
The Controller
public function search_vendors(Request $request){
$vendors = vendor::where('vendor_name','LIKE','%'.$request->vendor.'%')->get();
return response()->json($vendors);
}
The CSS
.autocomplete-box-li:hover {
background-color: #f2f2f2;
}
.autocomplete-box{
position: absolute;
z-index: 1;
}
If you want to get the id of the vendor you can do it using vendor.vendor_id which should be present in the vendor object which is returned from the server and if you want to populate the vendors array with new options you can have a watch or a #change (binding) function to add the entered text field as the new vendor in the vendor array. Also, I would suggest that you download the vue extension as it will help you a lot in debugging
<label>Vendor:</label>
<input type="text" v-model="vendor" v-on:keyup="get_vendors">
<div class="panel-footer" v-if="vendors.length">
<ul class="list-group">
<li class="list-group-item for="(vendor,index) in vendors">
{{ index }}
{{ vendor.vendor_id }}
{{ vendor.vendor_name }}
</li>
</ul>
</div>

List down an array of messages from the converstions

I would like to list down the messages from a chat Id ... I am using Vue js and i could get the data but i am not able to display them using the component . anyone would like to guide ?
This is my message component where the messages will be displayed here
<template>
<div class="row w-20 " >
<div class="card col-4 ">
<ul>
<li v-for="(conversation,index) in conversation" :key="conversation.id">
<div >
{{message}}
</div>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
props: ['conversation_index_route'],
data() {
return {
conversations: [],
url: 'http://127.0.0.1:8000/comms/conversation/'
}
},
beforeMount() {
this.$eventBus.$on('selectConversation', this.getConversations)
this.getConversations();
},
methods: {
getConversations(id) {
console.log(this.url+id);
axios.get(this.url+ id)
.then(response => {
this.conversations = response.data;
})
}
}
}
</script>
This are the data that can seen in VUE .. I need to display the messages which is in array
conversation_index_route:"http://127.0.0.1:8000/comms/conversation"
conversations:Object
all_staff_attended:false
centre_id:5
children:"3828,4197,7748,11591,12376,12394,12433,12441,12754,12755,12765,13284,14149,14602,14656,14941"
classes:"139"
cover_image:"https://via.placeholder.com/150x150"
created_at:"2020-06-09 19:14:20"
exited_users:null
id:258
last_id:1917
messages:Array[5]
0:"{"_id":1921,"text":"Okayyyy","createdAt":"2020-06-10 01:46:10","user":{"_id":13077,"name":"Mom (Alex,Jacob,Ahmad,Patrick,Ethan Lim)","avatar":null},"image":null,"video":null,"file":null,"images":{},"public_id":null,"read":{"0":13077,"1":14083,"2":3}}"
1:"{"_id":1920,"text":"Chvfhdgy","createdAt":"2020-06-10 01:46:00","user":{"_id":13077,"name":"Mom (Alex,Jacob,Ahmad,Patrick,Ethan Lim)","avatar":null},"image":null,"video":null,"file":null,"images":{},"public_id":null,"read":{"0":13077,"1":14083,"2":3}}"
2:"{"_id":1919,"text":"Heyyyy","createdAt":"2020-06-10 01:45:28","user":{"_id":14083,"name":"Siti","avatar":"https:\/\/api.cloudinary.com\/v1_1\/ds13udsoy\/image\/download?timestamp=1592882587&public_id=archaana%2Flibrary%2Fprofile%2Fstaff%2Fcd3ecc89-f67e-4e5e-89e9-badafd903bba_1591032813&type=private&expires_at=1592882647&signature=d0f12d520d18ff1a6b594bcb0ecb742f8ffd88a6&api_key=567141618229528"},"image":null,"video":null,"file":null,"images":{},"public_id":null,"read":{"0":14083,"1":13077,"2":3}}"
3:"{"_id":1918,"text":"Hello","createdAt":"2020-06-10 01:45:14","user":{"_id":14083,"name":"Siti","avatar":"https:\/\/api.cloudinary.com\/v1_1\/ds13udsoy\/image\/download?timestamp=1592882587&public_id=archaana%2Flibrary%2Fprofile%2Fstaff%2Fcd3ecc89-f67e-4e5e-89e9-badafd903bba_1591032813&type=private&expires_at=1592882647&signature=d0f12d520d18ff1a6b594bcb0ecb742f8ffd88a6&api_key=567141618229528"},"image":null,"video":null,"file":null,"images":{},"public_id":null,"read":{"0":14083,"1":13077,"2":3}}"
4:"{"_id":1917,"text":"Hahaha","createdAt":"2020-06-10 01:14:34","user":{"_id":13077,"name":"Mom (Alex,Jacob,Ahmad,Patrick,Ethan Lim)","avatar":null},"image":null,"video":null,"file":null,"images":{},"public_id":null,"read":{"0":13077,"1":181,"2":14083,"3":3}}"
parent_users:"2413,3461,11690,11770,11786,12262,12263,13077,14232,15275,16713"
parents:Array[11]
staff_users:"321,16707,12117,13488,14083"
staffs:Array[5]
status_id:1
title:"Class 0906"
updated_at:"2020-06-09 19:14:20"
url:"http://127.0.0.1:8000/comms/conversation/"
Can Anyone help me how to display the array of message in the component ..
Alright let's assume that this is how your response is structured:
{
all_staff_attended: false,
centre_id: 5,
messages: Array[5]
...etc.
}
Then when you call your getConversations method you could make your data property this.conversations equal to messages array from your response:
getConversations(id) {
console.log(this.url+id);
axios.get(this.url+ id)
.then(response => {
//from your response you would want to get messages array
this.conversations = response.data.messages;
})
}
Once you got your messages array, you can then loop through it with v-for like so:
<ul>
<li v-for="(conversation,index) in conversation" :key="conversation.id">
<div>
<p>Message: {{conversation.text}}</p>
<p>User: {{conversation.user.name}}</p>
<p>Created at: {{conversation.createdAt}}</p>
</div>
</li>
</ul>
Now, you can access each object of the messages array like in the example above.

Removing text from title in an array using Vue

I am trying to replace the text "this | " with "" from the titles in an array.
What is the best way to do this?
Any help would be greatly appreciated :)
my js code:
let Feed=require('rss-to-json')
Feed.load('http://localhost:3000/news', function (err, content) {
let appTitleList = new Vue({
el: '#news',
data: {
rssItems: content.items
},
methods:{
removeFunction: function () {
this.content.title = this.content.title.replace("this | ", "");
}
})
})
the html:
<div class="card" id="news">
<ul class="list-group list-group-flush">
<li class="list-group-item" v-for="item in rssItems" >
<b>{{ item.title }}</b>
<p>{{ item.description }}</p>
</li>
</ul>
</div>
I don't see what this.content is. I don't see where you are using removeFunction, but if you are, try this:
removeFunction: function () {
const rssItems = [...this.rssItems]
for (const item of rssItems) {
item.title = item.title.replace("this | ", "");
}
this.rssItems = rssItems
}
Alternatively, mutate the rssItems before setting them in the state, and maybe you won't need the removeFunction.
data: {
rssItems: content.items.map(i => ({
...i,
title: i.title.replace("this | ", "")
}))
}
This can be a possible solution: fetching your API's posts when the Vue.JS instance is created, mutating the related titles and enqueue each post.
<head>
... your imports from CDN
</head>
<body>
<div id="app">
<div class="card" id="news">
<ul class="list-group list-group-flush">
<li class="list-group-item" v-for="item in items">
<b>{{ item.title }}</b>
<p>{{ item.description }}</p>
</li>
</ul>
</div>
</div>
<script>
new Vue({
el: '#app',
data () {
return {
items: []
}
},
created () {
Feed.load('your-api-endpoint', (err, content) => {
// TODO: error handling...
for (let i = 0; i < content.items.length; i++) {
const item = content.items[i];
// Mutate the title and enqueue the post
item.title = item.title.replace('Title | ', '');
this.items.push(item);
}
});
}
})
</script>
</body>
Also, watch out that the field data in the Vue.JS instance must be a function, not an object. More about this, here.

Create autocomplete input Vue Js

I try to create a method that let the user to insert just value that exists in database, like an autocomplete.
Right now returns a list, but that list is not sorted, doesn't matter what I type the data from the list are the same.
<b-form-group label="Name" label-for="name-input">
<b-form-input
id="name-input"
v-model="query"
#keyup="autoComplete"
></b-form-input>
<div v-if="results.length">
<ul>
<li class="list-group-item" v-for="(result, index) in results" :key="index" id="display-none" #click="suggestionClick(result.name)">
{{ result.name }}
</li>
</ul>
</div>
</b-form-group>
autoComplete() {
this.results = [];
if (this.query.length > 2) {
get("/datafromapi", {
params: {
q: this.query
}
}).then(response => {
this.results = response.data.data;
});
}
},
suggestionClick(index) {
this.query = index
var element = document.getElementById("display-none");
element.classList.add("display-none");
},