To bind the the data directly to mat-checkbox in angular - angular8

I have the following mat-checkbox and I am passing the value has as shown in the code
<mat-checkbox [(ngModel)]="temperature" name="temperature" value='70' color="primary" [disabled] = "(!device) || humidity || pressure ||!(!cust_entry) || lesser ||equal || contain" disabled>Temperature</mat-checkbox>
This checkbox I am using inside the form whenver I post the data it is coming has in json response {"temperature":true} but I want like {"temperature":"70"}. I know we can use onclickevent but I have 20 checkboxes I can't able to do onclickevent for all checkboxes

https://material.angular.io/components/checkbox/examples
component.html
<section class="example-section">
<mat-checkbox class="example-margin" [(ngModel)]="checked">Checked</mat-checkbox>
<mat-checkbox class="example-margin" [(ngModel)]="indeterminate">Indeterminate</mat-checkbox>
</section>
component.ts
import {Component} from '#angular/core';
#Component({
selector: 'checkbox-configurable-example',
templateUrl: 'checkbox-configurable-example.html',
styleUrls: ['checkbox-configurable-example.css'],
})
export class CheckboxConfigurableExample {
checked = false;
indeterminate = false;
}

Related

How to use parameters and execute correctly a useLazyQuery from Apollo client in Vue 3?

I'm learning Apollo client with VueJs (Composition API syntax), I got a query that searches a user by the name field, and What I'm trying to do is to trigger the fetch with a #click event on a button next to an input in which you should write the user's name.
So basically I'm trying to use useLazyQuery and pass the name prop as param in the query but I don't know how to do it.
<div class="selectedUser">
<template>
<div class="container">
<input
type="text"
placeholder="Brian..."
v-model="userSearched"
/>
<p>{{userSearched}}</p>
<button
#click="load()">
Search for a user
</button>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, computed, reactive, toRefs } from 'vue';
import { useLazyQuery, useQuery } from '#vue/apollo-composable'
import gql from 'graphql-tag';
export default defineComponent({
name: 'HomeView',
setup(){
const GET_USER_BY_NAME = gql`
query getUser($name: String!){
user(name: $name) {
id
name
age
username
nationality
}
},
`
const state = reactive({
userSearched : ''
});
const {
result: userSearhedResult,
load
} = useLazyQuery(GET_USER_BY_NAME);
` return {
users,
error,
loading,
load,
...toRefs(state)
}
}});
</script>
As you can see, my idea is/was to use the userSearched from the reactive() as param, but I'm not doing it right. Hope you share with me the correct way to do it. Thanks

Teleport in component from slot Vue3

I want to create tabs component for my components library. I want tabs and tab components to work like this:
<b-tabs>
<b-tab
:title="'tab 1'"
:is-active="false"
>
tab content1
</b-tab>
<b-tab
:title="'tab 2'"
:is-active="false"
>
tab content2
</b-tab>
<b-tab
:title="'tab 3'"
:is-active="true"
>
tab content3
</b-tab>
</b-tabs>
So we have two components and they have some props including is-active which by default will be false.
The parent component - tabs.vue will be something like this
<template>
<section :class="mode ? 'tabs--light' : 'tabs--dark'" #change-tab="selectTab(2)">
<div :id="`tabs-top-tabId`" class="tabs__menu"></div>
<slot></slot>
</section>
</template>
here we have wrapper for our single tab which will be displayed here using slot. Here in this "parent" component we are also holding selectedIndex which specify which tab is selected and function to change this value.
setup () {
const tabId = Math.random() // TODO: use uuid;
const data = reactive<{selectedIndex: number}>({
selectedIndex: 0
})
const selectTab = (i: number) => {
data.selectedIndex = i
}
return {
tabId,
...toRefs(data),
selectTab
}
}
TLDR Now as you guys might already noticed in tab.vue I have div with class tabs__menu which I want to teleport some stuff into. As the title props goes into <tab> component which is displayed by the slot in tabs.vue I want to teleport from tab to tabs.
My tab.vue:
<template>
<h1>tab.vue {{ title }}</h1>
<div class="tab" v-bind="$attrs">
<teleport :to="`#tabs-top-tabId`" #click="$emit('changeTab')">
<span style="color: red">{{ title }}</span>
</teleport>
<keep-alive>
<slot v-if="isActive"></slot>
</keep-alive>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from 'vue'
export default defineComponent({
props: {
title: {
type: String as PropType<string>,
required: true
},
isActive: {
type: Boolean as PropType<boolean>,
required: true
}
// tabId: {
// type: Number as PropType<number>, // TODO: change to string after changing it to uuid;
// required: true
// }
}
})
</script>
However this span does not get teleported. When I run first snippet for this post I can't see it displayed and I don't see it in DOM.
Why teleported span doesnt display?
I came across this issue recently when using element-plus with vue test utils and Jest.
Not sure if this would help but here is my workaround.
const wrapper = mount(YourComponent, {
global: {
stubs: {
teleport: { template: '<div />' },
},
},
})

Angular undefined value of #input variable

I'm new to Angular and I have some issues , hope you'll help me.
so I'm trying to share a value of a variable from a ProjectComponent to an AcceuilComponent , the value of this variable is displaying correctly into my acceuil.component.html but when I try to use it into my acceuil.component.ts it's undefined !
project.component.html (the parent component)
<app-header-in></app-header-in>
<ng-sidebar-container>
<ng-sidebar [opened]="opened">
<p> Sidebar </p>
<button (click)="Sidebar()">
Close Sidebar
</button>
<ul class="menu">
<li class="hh"
*ngFor="let project of projects"
[class.selected]="project === selectedProject"
(click)="onSelect(project)">
{{project.nomprojet}}</li>
</ul>
</ng-sidebar>
<div ng-sidebar-content >
<br><br><br><br>
<button (click)="Sidebar()">
Open Sidebar
</button>
<app-acceuil [message]="idProject"></app-acceuil>
</div>
</ng-sidebar-container>
project.component.ts
import { Component, OnInit } from '#angular/core';
import { ApiService } from '../api.service';
import {ProjectService} from '../project.service';
import {PartService} from '../part.service';
#Component({
selector: 'app-project',
templateUrl: './project.component.html',
styleUrls: ['./project.component.css']
})
export class ProjectComponent implements OnInit {
opened=true;
projects:any;
idProject;
selectedProject;
constructor(private projectService:ProjectService) { }
ngOnInit(): void {
this.projectService.getProjects().subscribe((result)=>{console.log("result",result)
this.projects=result})
}
Sidebar(){
this.opened=!this.opened;
}
onSelect(pro): void {
this.idProject = pro.id;
}
}
acceuil.component.html (my child component)
<p>{{message}}</p>
<ul >
<li class="hh"
*ngFor="let part of parts">
{{part.nomparti}}
</li>
</ul>
acceuil.component.ts
import { Component, OnInit,Input } from '#angular/core';
import { ApiService } from '../api.service';
import {PartService} from '../part.service';
#Component({
selector: 'app-acceuil',
templateUrl: './acceuil.component.html',
styleUrls: ['./acceuil.component.css']
})
export class AcceuilComponent implements OnInit {
#Input() message;
parts:any;
constructor(private partService:PartService) {
}
ngOnInit(): void{
console.log("id",this.message);
this.partService.getPartsFromIdProject(this.message).subscribe((result)=>{console.log("result",result)
this.parts=result})
}
ngOnChanges() {
if(this.message) {
console.log(this.message)
}
}
}
I'm using the message to call a service and displaying data .
in the acceuil.component.html <p>{{message}}</p> is displaying correctly but console.log("id",this.message); in acceuil.component.ts displays undefined
As message is an input property, you need to get its value in ngOnchanges life cycle.
First time, when it is in ngOnChanges, input value will be undefined. So for the safe side, better to add a check for not undefiled condition like below
ngOnChanges(changes: SimpleChanges) {
if (changes.message) {
// Should be defined now
console.log(this.message);
}
}

how do I pass the value from child to parent with this.$emit

What I trying to achieve here is to pass the const randomNumber inside the child component [src/components/VueForm/FormQuestion.vue] that need to be passed to parent component [src/App.vue]. Therefore I use $emit to pass the date, but since this is my first time working with $emit, I am not really sure how to do that. Could someone help me with this.
In order to run this app, I would add a working code snippet. Click on the start button and fill in the input fields. When the input field validates correctly it will pop up the button and if the user clicks on that is should pass the data to the parent. At the end it should be stored inside the App.vue in localStorage, so therefore I want to receive the randomNumber from that child component.
working code snippet here
// child component
<template>
<div class="vue-form__question">
<span class="question" :class="{ big: !shouldShowNumber }"> {{ getRandomNumber() }} </span>
</div>
</template>
<script>
export default {
methods: {
getRandomNumber() {
const randomNumber = Math.floor((Math.random() * 3) + 1);
const question = this.question.question;
this.$emit('get-random-number', question[randomNumber]);
return question[randomNumber];
}
}
};
// parent component
<template>
<div id="app">
<vue-form
:data="formData"
#complete="complete"
#getRandomNumber="newRandomNumber"
></vue-form>
</div>
</template>
<script>
import VueForm from "#/components/VueForm";
import data from "#/data/demo";
export default {
data() {
return {
formData: data
}
},
components: {
VueForm
},
created() {
this.complete()
},
methods: {
complete(data) {
// Send to database here
// localStorage.setItem('questions', data.map(d => d.question[this.randomNumber] + ': ' + d.answer));
},
}
};
</script>
v-on:get-random-number (or the superior short-hand syntax: #get-random-number). Just like you'd listen to any other event, such as #click or #mouseenter.
Though I don't know off the top of my head if dashes are valid in event names. Might have to camelcase it.

How to get data from a nested component

I have this 3 components. One is for the Question component that consists of questions. The second is for QuestionOption for the list of choices. And the third one is my main component. How do I get the data from the QuestionOption component to the main component. Since the main component is not the parent of the QuestionOption I cannot use the $emit. Also I make use of bus but it's not working on my case. Can anyone help me on this.
Also how will I get all the chosen answers after the submission of the button? Here is my code.
Main.vue
<div class="quiz-background">
<question
v-for="(question, $indexParent) in randomQuestions"
:question="question['doc'].question"
:choices="question['doc']['choices']"
:indexParent="$indexParent"
:correctAnswer="question['doc'].correctAnswer"
>
</question>
<section style="margin:16px">
<v-ons-button
modifier="cta"
#click="submit"
v-show="!isDone"
>Submit
</v-ons-button>
</section>
</div>
<script>
submit() {
bus.$on('choosed', function(answer) {
console.log(answer);
});
},
</script>
Question.vue
<template>
<v-ons-list>
<v-ons-list-header>
{{indexParent + 1}}.{{ question }}
</v-ons-list-header>
<question-option
v-for="(choice, key, $index) in choices"
:choice="choice"
:letter="key"
:indexParent="indexParent"
:index="$index"
:correctAnswer="correctAnswer"
>
</question-option>
</v-ons-list>
</template>
<script>
import QuestionOption from './QuestionOption.vue';
export default {
props: ['question', 'indexParent', 'choices', 'correctAnswer'],
components: {
QuestionOption
}
}
</script>
QuestionOption.vue
<template>
<v-ons-list modifier="inset">
<v-ons-list-item
:name="'question-' + indexParent"
:modifier="longdivider"
:key="letter"
tappable
>
<label class="left">
<v-ons-radio
:name="'question-' + indexParent"
:input-id="indexParent + '-' + index"
:value="letter"
:key="letter"
v-model="chosenAnswer"
#change="appendAnswer($event)"
>
</v-ons-radio>
</label>
<label
class="center"
:for="indexParent + '-' + index"
:class="{'success' : isSuccess, 'danger' : isDanger}"
>
{{ letter }} . {{ choice }}
</label>
</v-ons-list-item>
</v-ons-list>
</template>
<script>
import Vue from 'vue';
var bus = new Vue();
export default {
data() {
return {
chosenAnswer: ''
}
},
props: ['letter', 'choice','correctAnswer', 'indexParent', 'index'],
computed: {
isSuccess () {
return this.chosenAnswer === this.correctAnswer;
},
isDanger () {
return this.chosenAnswer !== this.correctAnswer;
}
},
methods: {
appendAnswer (event) {
var answer = event.target.value;
bus.$emit('choosed', answer);
}
}
}
</script>
Like the article I mentioned in the comment, you can make a js file called event-bus.js, include code below.
// event-bus.js
import Vue from 'vue';
var EventBus = new Vue();
export default EventBus;
After that, import it both in QuestionOption.vue and Main.vue like this
import bus from './event-bus';
Then try it again. The reason why your code didn't work is because you generated two Vue instances, they've got no relationship with each other, so no communication would happen.