Pass ID(Index) to onEditDetail() Parameters - javascript

How can i pass the value index or id to EditDetail() parameters. I want it to be put inside the parenthesis of onEditDetail() once i click the onEditDetail() in html
ngOnInit() {
this.route.params
.subscribe((params: Params) => {
this.id = +params['id'];
this.user = this.userService.getUser(this.id);
});
}
onEditDetail(id: string) {
console.log(id);
}
user-detail.component.html
<div class="container">
<div class = "row">
<div class="col-md-3"></div>
<div class = "col-md-8">
<div class="card">
<div class="card-header">
{{ user.l_name}} 's Complete Information<span class="pull-right"><input class="form-control" placeholder="Search User" name="srch-term" id="srch-term" type="text"></span>
</div>
<table class="table table-responsive">
<thead class="thead-default">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Contact Number</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ user.f_name }}</td>
<td>{{ user.l_name }}</td>
<td>{{ user.contact_no }}</td>
<td><button class=" btn btn-primary" style="cursor: pointer;" (click)="onEditDetail()">Edit</button> </td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>

Adding to other answers,
You need to understand that you are making an asynchronous call.
So If you need to access id anywhere else, you need to get that on completion of asynchronous call, not before that.
And this is reason, you need to call onEditDetail() inside Subscribe block as last parameter.
there are 3 params to subscribe.
Data which is returned by call,
Error if any occured.
On complete if you wish to do something.
In your case, as 3rd parameter, you have to call onEditDetail method
ngOnInit() {
this.route.params
.subscribe((params: Params) => {
this.id = +params['id'];
this.user = this.userService.getUser(this.id);
// 3rd parameter, this is where call is subscribe is completed
this.onEditDetail(this.id);
});
}

You can do that
ngOnInit() {
this.route.params
.subscribe((params: Params) => {
this.id = +params['id'];
this.user = this.userService.getUser(this.id);
// Your method call
this.onEditDetail(this.id);
});
}
onEditDetail(id: string) {
console.log(id);
}

ngOnInit() {
this.route.params
.subscribe((params: Params) => {
this.id = +params['id'];
this.onEditDetail(this.id); //call onEditDetails and pass id to it.
this.user = this.userService.getUser(this.id);
});
}
onEditDetail(id: any) {
console.log(id);
}

Related

Button that adds a new row when clicked in Vue 3

First I must say that I'm a complete newbie in coding and Vue it's the first framework I'm learning and I'm terrible working with arrays at the moment. In the practice I am doing I am displaying the first five elements of the array in a table (I've filtered them in a new variable to do the v-for).
Now I need to add a button that when clicked will show me a new row of the original array, but I'm a bit stuck on how to do it. As u may see in the code below, contactList is the variable that has all the data, but I have no clue how to link it to the filtered one to show more data when clicked.
<template>
<h1 class="display-1 text-primary">Contacts</h1>
<button type="button" class="btn btn-outline-primary btn-lg" #click="addRandom">Add random</button>
<div class="container container__pos">
<table class="table table-hover">
<thead>
<tr>
<th class="col col__style">Picture</th>
<th class="col col__style">Name</th>
<th class="col col__style">Popularity</th>
<th class="col col__style">Won an Oscar</th>
<th class="col col__style">Won an Emmy</th>
</tr>
</thead>
<tbody>
<tr v-for="(element, index) of contactListed" :key="index">
<td scope="row">
<img
:src="element.pictureUrl"
:alt="element.name + ` image`"
class="image"
/>
</td>
<td> {{ element.name }}</td>
<td>{{ element.popularity }}</td>
<td>{{ wonAward(element.wonOscar) }}</td>
<td>{{ wonAward(element.wonEmmy) }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import contacts from "./contacts.json";
export default {
data() {
return {
contactList: contacts,
contactListed: contacts.slice(0, 5),
};
},
methods: {
wonAward(element) {
if (element === true || element === true){
return "winner";
} else {
return "";
}
},
},
};
</script>
You can use a computed variable that holds the first N elements of the array, and have your button increment the value of N, like this:
<script>
import contacts from "./contacts.json";
export default {
data() {
return {
contactList: contacts,
nItems: 5
};
},
computed: {
contactListed() {
return this.contacts.slice(0, this.nItems)
}
},
methods: {
addRow() {
this.nItems++;
},
wonAward(element) {
if (element === true || element === true){
return "winner";
} else {
return "";
}
},
},
};
</script>
<template>
...
<button #click="addRow()" />
</template>

Fetched data duplicates itself after sorting

I fetched data by using fetch api into a table. I sort my data by clicking on column headers. It works but after it's sorted,it duplicates data. I checked on it,but i guess there's someting i've missed.
let data =[];
function veriAl()
{
fetch('https://jsonplaceholder.typicode.com/users')
.then(response =>{
if(!response.ok)
{
throw Error("ERROR");
}
return response.json();
})
.then(veri => {
data=veri;
veriEkle(data);
}).catch(error => {
console.log(error);
});
}
const sort_data = (field) =>
{
data.sort((a,b) => {
let valueA=a[field];
let valueB= b[field];
if(valueA<valueB)
{
return -1;
}
else if(valueB>valueA)
{
return 1;
}
return 0;
})
console.log("sıralandı"+field+"e göre",data);
veriEkle(data);
}
const veriEkle =(array)=>
{
const html=array.map(user =>{
return `<table class="user">
<td> ${user.id}</td>
<td>${user.name}</td>
<td>${user.username}</td>
<td>${user.email}</td>
<td>${user.address.street}/${user.address.suite}/${user.address.city}</td>
</table>
`;
}).join("");
console.log(html); document.querySelector('#veri_tablo').insertAdjacentHTML("afterbegin",html);
}
veriAl();
<div class="container">
<div class="row justify-content-center">
<table class="table" id="veri_tablo">
<thead class="thead-dark">
<tr>
<th onclick="sort_data('id')">ID</th>
<th onclick="sort_data('name')">Name</th>
<th onclick="sort_data('username')">Username</th>
<th onclick="sort_data('email')">Email</th>
<th onclick="sort_data('address')">Adres</th>
</tr>
</thead>
</table>
<div>
</div>
console.log("sıralandı"+field+"e göre",data);
veriEkle(data); //---->Here
You should maybe edit here like veriEkle(...data); or you should use filter function instead of "sort"
There seems to be nothing wrong with your data. It's not being duplicated. It is the html that's being duplicated. You're appending html without removing the existing entries. You should have a container element and change the inner html of that container instead.
Your js should look something like this...
//...
const veriEkle = (array) => {
const html = array.map(user => {
return `<tr class="user">
<td> ${user.id}</td>
<td>${user.name}</td>
<td>${user.username}</td>
<td>${user.email}</td><td>${user.address.street}/${user.address.suite}/${user.address.city}</td>
</tr>
`;
}).join("");
console.log(html);
document.getElementById('table_content').innerHTML = html;
}
And your html
<div class="container">
<div class="row justify-content-center">
<table class="table" id="veri_tablo">
<thead class="thead-dark">
<tr>
<th onclick="sort_data('id')">
ID
</th>
<th onclick="sort_data('name')">
Name
</th>
<th onclick="sort_data('username')">
Username
</th>
<th onclick="sort_data('email')">
Email
</th>
<th onclick="sort_data('address')">
Adress
</th>
</tr>
<tbody id="table_content" /> //the container element
</thead>
</table>
<div />
</div>
</div>
PS Using the innerHTML property is not considered best practice and you should look at this link for the best ways to create and render elements from html strings.

Get value from array data in Vue

I'm kinda new to Vue and i'm struggling to get one value from an array. I'm making an axios get request where I return an array of users containing the values (name, display_name, role, and few others fields). I'm able to get all these values and mount my table with the component below:
<template>
<div class="container">
<table class="mt-3 table roboto table-stripped table-hover table-sm">
<thead class="thead-light">
<th>Name</th>
<th>Username</th>
<th>Profile</th>
<th class="text-center">Is manager</th>
</thead>
<tbody v-for="user in users">
<td v-text="user.name"></td>
<td v-text="user.username"></td>
<td v-text="user.display_name"></td>
<td class="text-center">
<button
class="letter-shadow btn-sm font-500 grey-darkest roboto letter-spacing"
:class="showRole">Activate
</button>
</td>
</tbody>
</table>
</div>
</template>
<script>
export default {
data() {
return {
users: [],
}
},
computed: {
showRole() {
// wanted to diff button colors here
}
},
mounted() {
axios.get('/api/users').then(response => this.users = response.data);
},
}
</script>
So I wanted to modify that class showRole depending on the value of user.display_name, if the user.display_name is equal to "Manager" e.g. I would show a btn-danger. I just don't know how can I get this value to compare, if I try to use this.user.display_name on showRole method I get nothing (undefined). Thanks for any help.
I think you should use a method instead, as you can't pass parameters to computed properties.
Use this
...
methods : {
showRole(user){
//code that returns the button class
}
}
...
<button :class="showRole(user)">Activate

Routing using object.$key returns undefined - firebase

I want to route the link by using $key in the firebase. However, after going through all the documentations and forums, the answer that I get is to use object.$key to retrieve the value. I use it and it still returns undefined.
<table class="table">
<thead>
<tr>
<th>Title</th>
<th>Price</th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let p of products$ | async">
<td>{{ p.title }}</td>
<td>{{ p.price }}</td>
<td>
<a [routerLink]="['/admin/products/', p.$key]">Edit</a>
</td>
</tr>
</tbody>
products$ returns an observable of the AngularFireList
products$;
constructor(private productService: ProductService) {
this.products$ = this.productService.getAll().valueChanges();
}
This is the Product Service definition.
export class ProductService {
constructor(private db: AngularFireDatabase) { }
create(product) {
return this.db.list('/products').push(product);
}
getAll() {
return this.db.list('/products');
}
get(productId) {
return this.db.object('/products/' + productId);
}
}
I still am unsure what is wrong with this as it returns /admin/products/undefined
As all of the reference I read state in using this object.$key
.$key is no longer present in AngularFire2 v5. If you need the key use snapshotChanges() see our migration guide for more details.
constructor(private productService: ProductService) {
this.products$ = this.productService.getAll().snapshotChanges();
}
Then use the payload in your view:
<table class="table">
<thead>
<tr>
<th>Title</th>
<th>Price</th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let p of products$ | async">
<td>{{ p.payload.val().title }}</td>
<td>{{ p.payload.val().price }}</td>
<td>
<a [routerLink]="['/admin/products/', p.key]">Edit</a>
</td>
</tr>
</tbody>
Or you could map the snapshot changes into a structure you're more familar with:
constructor(private productService: ProductService) {
this.products$ = this.productService.getAll()
.snapshotChanges()
.map(s => ({"$key": s.key, ...s.payload.val()}))
}

Vue.js $remove not removing element after deleted from database

I am using Laravel and trying to learn Vue.js. I have a delete request that is working properly and deleting the object from the database. The problem is that it is not being removed from the DOM after the successful deletion. I am using the $remove method and passing it the full object, so I know I'm missing something.
As a side note, I have a main.js as an entry point with a PersonTable.vue as a component. The PersonTable.vue holds the template and script for that template.
Here is my Laravel view:
<div id="app">
<person-table list="{{ $persons }}">
</person-table>
</div>
And here is my `PersonTable.vue:
<template id="persons-template">
<div class="container">
<div class="row">
<div class="col-sm-12">
<h1>Persons List</h1>
<table class="table table-hover table-striped">
<thead>
<tr>
<td>First Name</td>
<td>Last Name</td>
<td>Email</td>
<td>Gender</td>
</tr>
</thead>
<tbody>
<tr v-for="person in list">
<td>{{person.first_name }}</td>
<td>{{person.last_name }}</td>
<td>{{person.email }}</td>
<td>{{person.gender }}</td>
<td><span #click="deletePerson(person)">X</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
<script>
export default {
template: '#persons-template',
props: ['list'],
methods: {
deletePerson: function(person) {
this.$http.delete('/person/' + person.id).then(
function(response) {
this.persons.$remove(person);
}
);
}
},
created: function() {
this.persons = JSON.parse(this.list);
}
};
</script>
And my main.js entry point:
var Vue = require('vue');
Vue.use(require('vue-resource'));
var Token = document.querySelector('meta[name="_token"]').getAttribute('content');
Vue.http.headers.common['X-CSRF-TOKEN'] = Token;
import PersonTable from './components/PersonTable.vue';
new Vue({
el: '#app',
components: { PersonTable },
})
I think you need to bind this to the response function:
function(response) {
this.persons.$remove(person);
}.bind(this)
That way when you do this.persons you are still referring to the Vue component
edit: could try -
props:['personJson'],
data:function(){
return {
persons:[]
}
},
ready:function(){
this.persons = JSON.parse(this.personJson)
}
Thinking maybe since persons is a string initially, Vue isn't binding the reactive capabilities properly?
I think that you need to use the this.$set in your created method, if you don't, I am afraid that Vue would lose reactivity.
In your created method, could you try the following:
export default {
template: '#persons-template',
props: ['persons'],
methods: {
deletePerson: function(person) {
var self = this;
this.$http.delete('/person/' + person).then(
function(response) {
self.persons.$remove(person);
}
);
}
},
created: function() {
this.$set('persons',JSON.parse(this.persons));
}
};
Finally figured it out. I needed to pass the JSON data to my data property of the component. Here is the code.
In the blade file:
<div id="app">
<person-table list="{{ $persons }}">
</person-table>
</div>
In my PersonTable.vue file:
<template id="persons-template">
<div class="container">
<div class="row">
<div class="col-sm-12">
<h1>Persons List</h1>
<table class="table table-hover table-striped">
<thead>
<tr>
<td>First Name</td>
<td>Last Name</td>
<td>Email</td>
<td>Gender</td>
</tr>
</thead>
<tbody>
// Notice how I am using persons here instead of list
<tr v-for="person in persons">
<td>{{person.first_name }}</td>
<td>{{person.last_name }}</td>
<td>{{person.email }}</td>
<td>{{person.gender }}</td>
<td><span class="delete person" #click="deletePerson(person)"><i class="fa fa-close"></i></span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
<script>
export default {
template: '#persons-template',
props: ['list'],
data: function() {
return {
persons: []
}
},
methods: {
deletePerson: function(person) {
this.$http.delete('/person/' + person.id).then(
function(response) {
this.persons.$remove(person);
}
);
},
},
created: function() {
// Pushing the data to the data property so it's reactive
this.persons = JSON.parse(this.list);
},
};
</script>
Thanks to everyone for their contributions. I almost ditched Vue because of how long it has taken to fix this error.

Categories

Resources