Draggable table with bootstrap - draggable

i would like to make the rows in the table draggable but everything i tried didnt work.
i am realy new to programming and must do the task as soon as possible:)
i am realy thankful for your help`
i read all about b-table documentation in bootstrap but it doesnt say anything about the draggable rows in a table.
<script>
import BaseSafetyModal from '#/components/Base/BaseSafetyModal';
import draggable from "vuedraggable";
export default {
components: {
'safety-modal': BaseSafetyModal,
draggable
},
props: {
fields: {
type: Array,
required: true
},
items: {
type: Array,
required: true
},
approved: {
type: Boolean,
default: false
}
},
methods: {
getModalId (item) {
let name = Object.keys(item).find(
itemKeys =>
itemKeys.indexOf('id') > -1 &&
itemKeys !== 'headline_id' &&
itemKeys !== 'revision_id' &&
itemKeys !== 'building_id'
);
if (
Object.keys(item).indexOf('geometry_id') > -1 &&
Object.keys(item).indexOf('level_id') > -1
)
name = 'level_id';
return `${name}-${item[name]}`;
},
showModal (item) {
this.$root.$emit('bv::show::modal', `safety-modal-${this.getModalId(item)}`);
},
removeItem (item) {
this.$emit('removeItem', item);
this.$root.$emit('bv::hide::modal', `safety-modal-${this.getModalId(item)}`);
}
}
};
</script>
<template>
<div>
<b-row>
<b-col>
<slot name="button1"></slot>
<b-button
v-if="$store.state.permissions.location_permission > 10 && !approved && items.length > 2"
v-b-tooltip.hover
title="Eintrag hinzufügen"
class="float-right"
variant="primary"
#click="$emit('changeMode')"
>
<font-awesome-icon icon="plus"/>
</b-button>
</b-col>
</b-row>
<b-row>
<b-col class="pt-3">
<b-table fixed outlined striped hover stacked="md" :items="items" :fields="fields">
<template v-slot:cell(actions)="row">
<div class="text-md-right float-right">
<b-button-group size="sm">
<slot :item="row.item"></slot>
<b-button
v-b-tooltip.hover
title="Bearbeiten"
v-if="$store.state.permissions.location_permission > 10 && !approved"
type="button"
variant="primary"
#click="$emit('changeMode',row.item)"
>
<font-awesome-icon icon="edit"/>
</b-button>
<b-button
#click="showModal(row.item)"
v-b-tooltip.hover
title="Löschen"
v-if="$store.state.permissions.location_permission > 10 && !approved"
type="button"
variant="danger"
>
<font-awesome-icon icon="trash"/>
</b-button>
<safety-modal
:modal-id="`safety-modal-${getModalId(row.item)}`"
#removeItem="removeItem(row.item)"
></safety-modal>
</b-button-group>
</div>
</template>
</b-table>
</b-col>
</b-row>
<b-row>
<b-col>
<slot name="button2"></slot>
<b-button
v-if="$store.state.permissions.location_permission > 10 && !approved"
v-b-tooltip.hover
title="Eintrag hinzufügen"
class="float-right"
variant="primary"
#click="$emit('changeMode')"
>
<font-awesome-icon icon="plus"/>
</b-button>
</b-col>
</b-row>
</div>
</template>
`

You probably gonna need some drag and drop package, such as SortableJS or vue-smooth-dnd.
Let us now!

Related

How to disactivate the last breadcrumb in InertiaJS?

I am trying to disactivate the last crumb in InertiaJS (Laravel + Vue3) but I think I have an error or something missing somewhere. The error I am getting is the "isLast" is not defined.
isLast: This method simply takes in an index of the crumb array and checks if that crumb is the last one in the list.
selected: This is a simple method that emits an event whenever a crumb is selected. The event is then caught by Example.vue…
Here is the code:
BreadCrumb.vue
<template>
<div>
<ol class="inline-flex items-center space-x-1 md:space-x-3">
<li
v-for="(crumb, ci) in crumbs"
:key="ci"
>
<div class="inline-flex items-center">
<icon name="arrow"/>
<Link :href="`/${crumb}`" as="button" type="button" :class="{ disabled: isLast(ci) }" #click="selected(crumb)" class="capitalize" >
{{ crumb }}
</Link>
</div>
</li>
</ol>
</div>
</template>
<script>
import { Link } from '#inertiajs/inertia-vue3'
import Icon from '#/Shared/Icon'
export default {
components: {
Icon,
Link,
},
props: {
crumbs: {
type: Array,
required: true,
},
},
methods: {
isLast(index) {
return index === this.crumbs.length - 1;
},
},
}
</script>
Example.vue
<template>
<div class="md:p-12 md:pt-1">
<breadcrumb class="flex pl-4 mb-12" :crumbs="crumbs" #selected="selected"></breadcrumb>
</div>
</template>
<script>
import Breadcrumb from '#/Shared/Breadcrumb'
export default {
components: {
Breadcrumb,
},
return {
crumbs: ['home','users', 'create'],
}
methods: {
selected(crumb) {
console.log(crumb);
},
},
}
</script>
I would recommend binding the disabled-attribute
<Link ... :disabled="isLast(ci)" >
👆

Is there any option to have one common vuetify rule for two text fields

I have to fill either text-field-1 or text-field-2 or both In a form and I should be able to proceed with save
I tried having a flag variable but I that results in clicking on text-field-1 or text-field-2 to activate the save button
You can use computed property according to your need here is the basic example
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
valid: true,
firstName: '',
lastName: '',
nameRule: [
v => !!v || 'Name is required',
v => (v && v.length <= 10) || 'Name must be less than 10 characters',
],
}),
computed: {
nameRules () {
if(this.firstName.length == 0 && this.lastName.length == 0){
return this.nameRule;
}
if(this.firstName.length > 0 || this.lastName.length > 0 ){
return [];
}
},
},
methods: {
validate () {
this.$refs.form.validate()
},
reset () {
this.$refs.form.reset()
},
resetValidation () {
this.$refs.form.resetValidation()
},
},
})
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app id="inspire">
<v-form
ref="form"
v-model="valid"
lazy-validation
>
<v-text-field
v-model="firstName"
:counter="10"
:rules="nameRules"
label="First name"
></v-text-field>
<v-text-field
v-model="lastName"
:counter="10"
:rules="nameRules"
label="Last name"
></v-text-field>
<v-btn
:disabled="!valid"
color="success"
class="mr-4"
#click="validate"
>
Validate
</v-btn>
<v-btn
color="error"
class="mr-4"
#click="reset"
>
Reset Form
</v-btn>
<v-btn
color="warning"
#click="resetValidation"
>
Reset Validation
</v-btn>
</v-form>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>

show editable field when empty

I have this problem: I have a component with which I create editable fields.
If the field is already populated, everything works fine. I see the database value, I can click on it and change it.
If, on the other hand, in the database that value is empty, it is "hidden" in the view. In this way it is not possible to click on it to insert a value in the editable field.
I tried to get around the obstacle by inserting a: placeholder = "placeholder" but I don't even see that.
How can I do?
This is my visualization file:
<div class="py-0 sm:grid sm:grid-cols-10 sm:gap-4 my-2">
<dt class="text-md leading-6 font-medium text-gray-900 sm:col-span-2 self-center">
{{ $trans('labels.description') }}
</dt>
</div>
<div class="py-1 sm:grid sm:grid-cols-10 sm:gap-4">
<dd class="text-sm leading-5 text-gray-600 sm:mt-0 sm:col-span-10 self-center">
<v-input-text-editable
v-model="task.description"
#input="updateTask()"
:placeholder = "placeholder"
/>
</dd>
</div>
props: {
users: {
type: Array,
default: []
},
description: {
type: String,
default: null
}
},
data() {
return {
task: new Form({
description: this.description
})
}
},
this is my component:
<template>
<div class="block w-full">
<div v-if="!editable" class="cursor-pointer" #click="enableEditMode()">
{{ valueAfterEdit }}
</div>
<div v-else class="mt-1 flex rounded-md shadow-sm" v-click-outside="handleClickOutside">
<div class="relative flex-grow focus-within:z-10">
<input #keyup.enter="commitChanges()" class="form-input block w-full rounded-none rounded-l-md transition ease-in-out duration-150 sm:text-sm sm:leading-5" v-model="valueAfterEdit" ref="input"/>
</div>
<span class="btn-group">
<button #click="discardChanges()" type="button" class="btn btn-white rounded-l-none border-l-0">
<svg class="h-4 w-4 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
<path d="M10 8.586L2.929 1.515 1.515 2.929 8.586 10l-7.071 7.071 1.414 1.414L10 11.414l7.071 7.071 1.414-1.414L11.414 10l7.071-7.071-1.414-1.414L10 8.586z"/>
</svg>
</button>
<button #click="commitChanges()" type="button" class="btn btn-white">
<svg class="h-4 w-4 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
<path d="M0 11l2-2 5 5L18 3l2 2L7 18z"/>
</svg>
</button>
</span>
</div>
</div>
</template>
<script>
export default {
props: {
value: {
type: String,
default: null
},
allowEmpty: {
type: Boolean,
default: false
}
},
data() {
return {
editable: false,
valueBeforeEdit: this.value,
valueAfterEdit: this.value
}
},
watch: {
value(val) {
this.valueBeforeEdit = val;
}
},
methods: {
handleClickOutside() {
this.disableEditMode();
this.commitChanges();
},
enableEditMode() {
this.editable = true;
this.$emit('edit-enabled');
this.$nextTick(() => {
this.$refs.input.focus();
});
},
disableEditMode() {
this.editable = false;
this.$emit('edit-disabled');
},
commitChanges() {
if (!this.allowEmpty && this.valueAfterEdit !== '.') {
this.$emit('input', this.valueAfterEdit);
this.disableEditMode();
}
},
discardChanges() {
this.valueAfterEdit = this.valueBeforeEdit;
this.disableEditMode();
}
}
}
</script>

Usng Vuetify v-data-table how to set chip color based and value and item

I would like to set the chip color for the value of an item in a v-data-table using both the items value and the items id. So i want to set values under 0.5 to red only if the id is "Cl2". ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
[enter image description here][1]
Here's my table and code:
[1]: https://i.stack.imgur.com/Sp8DQ.jpg
<template>
<v-data-table
:headers="headers"
:items="parameters"
class="elevation-1"
hide-default-footer
calculate-widths
dense
>
<template v-slot:top>
<v-toolbar flat color="white">
<v-toolbar-title>Parameter Input {{ scanSite }} </v-toolbar-title>
<v-divider class="mx-4" inset vertical></v-divider>
<v-spacer></v-spacer>
<v-dialog v-model="dialog" persistent>
<v-card
max-width="315px"
max-height="240px"
style="position: absolute; top: 90px; left: 30px; right: 30px;"
>
<v-card-title>
<span class="">{{ editedItem.name }} - Enter/Edit Values </span>
</v-card-title>
<v-card-text class="card-text py-0 my-0">
<v-container>
<v-row class="row py-0">
<v-col cols="5">
<v-text-field
v-model="editedItem.value"
label="Value"
></v-text-field>
</v-col>
<v-col cols="5">
<v-text-field
v-model="editedItem.sid"
label="Save ID"
></v-text-field>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text #click="close">Cancel</v-btn>
<v-btn color="blue darken-1" text #click="save">Save</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-toolbar>
</template>
<template v-slot:[`item.actions`]="{ item }">
<v-icon small class="mr-2" #click="editItem(item)">
mdi-pencil
</v-icon>
<v-icon small class="mr-2" #click="addItem(item)">
mdi-plus
</v-icon>
</template>
<template v-slot:[`item.analyse`]="{ item }">
<v-simple-checkbox
color="green"
v-model="item.analyse"
></v-simple-checkbox>
</template>
<template v-slot:[`item.value`]="{ item }">
<v-chip :color="getColor(item.value)" small dark>{{ item.value }}</v-chip>
</template>
</v-data-table>
</template>
<script>
import { mapState } from "vuex";
export default {
data() {
return {
scanSite: "",
dialog: false,
selected: [],
editedItem: {
name: "",
value: 0,
sid: 0
}
};
},
computed: {
...mapState(["scanSite", "headers", "parameters", "sites"])
},
methods: {
editItem(item) {
this.editedIndex = this.parameters.indexOf(item);
this.editedItem = Object.assign({}, item);
this.dialog = true;
},
save() {
Object.assign(this.parameters[this.editedIndex], this.editedItem);
this.dialog = false;
},
close() {
this.dialog = false;
},
getColor(value, id) {
console.log(value, id);
if (value > 0.5 && id == "Cl2") return "red";
else if (value > 10) return "orange";
else return "green";
},
addItem(item) {
this.editedIndex = this.parameters.indexOf(item);
this.editedItem = Object.assign({}, item);
this.parameters.push(this.editedItem);
this.dialog = true;
}
}
};
</script>
I think you need to set both paramareters when you call your getColor() function, like so
<v-chip :color="getColor(item.value, item.id)" small dark>{{ item.value }}</v-chip>
or pass the whole item object and manage it in the getColor() function
<v-chip :color="getColor(item)" small dark>{{ item.value }}</v-chip>
...
getColor(item) {
if (item.value > 0.5 && item.id == "Cl2") return "red";
else if (item.value > 10) return "orange";
else return "green";
},

How to use the selection from my vue component in my blade file

I have build a vue-component which takes a list of objects and two criteria lists as props. The select lists are passed to two select inputs in the template. When either one is changed the list is filtered using the selected criteria. How do I get access to this filtered list in my blade file?
Here is my code.
Blade file:
<subjecttable-select :data-subjecttable="{{$subjectslessons->toJson()}}"
:data-departments="{{$departments->toJson()}}"
:data-subjects="{{$subjects->toJson()}}" #input="selectedsubjects">
</subjecttable-select>
#{{selectedsubjects}}
Vue-component
<template>
<div >
<div class="row mb-2 mx-2">
<form class="form-inline justify-content-between" >
<div class="form-group row mb-1">
<label class="col-auto col-form-label text-md-left" for="department">Leerjaar</label>
<div class="col-auto">
<select id= "department" class="form-control form-control-sm custom-select" v-model="department" #change="select()">
<option v-for="department_item in dataDepartments" :value="department_item['id']">
{{department_item["name"]}}
</option>
</select>
</div>
</div>
<div class="form-group row">
<label class="col-auto col-form-label text-md-leftt" for="subject">Vak</label>
<div class="col-auto">
<select id="subject" class="form-control form-control-sm custom-select" v-model="subject" #change="select()">
<option v-for="subject_item in dataSubjects" :value="subject_item['id']">
{{subject_item["description"]}}
</option>
</select>
</div>
</div>
<button class="btn-outline-primary" #click="reset()">Reset</button>
</form>
</div>
</div>
</template>
<script>
export default {
name:"subjecttable-select",
props: {
dataDepartments: { type: Array, required: true },
dataSubjects:{ type: Array, required: true},
dataSubjecttable: {type: Array, required: true },
value:{},
},
data() {
return {
selected:this.dataSubjecttable,
subject:"",
department:"",
}
},
methods:{
select(){
var item;
console.log(this.subject);
this.selected=[];
for(item of this.dataSubjecttable){
if(//get the subbejctlessons who are in the selected department
(this.department==="" || item["department_id"]===this.department) &&
//whose subject is the selected subject
(this.subject===""|| item["subject_id"]===this.subject)
){
this.selected.push(item);
}
}
this.$emit('input',this.selected);
},
reset(){
this.value = this.dataSubjecttable;
this.subject = "";
this.department="";
},
},
created(){
this.select();
},
filters: {
dateFilter(value){
var isDate = !isNaN(Date.parse(value));
if (isDate ){
var dateValue=new Date(value);
return dateValue.toLocaleDateString();
}
else{
return value;
}
}
},
};
</script>
app.js
Vue.component('subjecttable-select', require('./components/SubjectSelection.vue').default);
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
const app = new Vue({
el: '#app',
});
As you can see I emit an input event in my component but I have trouble accessing the value in the blade file.
Ideally, I think you want to do is load your SelecttableSelect component within another parent Vue component. This will allow you to trickle your events down to the parent component and use the data much more easily.
I have not tested this, but it's along the lines of what I would do to get started. You would need to format the output to your needs.
Lessons.vue
<template>
<div>
<!-- YOUR SELECT IS NOW DEFINED HERE, NOT IN THE BLADE FILE -->
<!-- Select -->
<subjecttable-select :data-subjecttable="dataSubjecttable"
:data-departments="dataDepartments"
:data-subjects="dataSubjects"
#input="updateResults"
>
</subjecttable-select>
<!-- End Select -->
<!-- Department -->
<div>
<h1>Department</h1>
<div v-if="results.department_id > 0">
<ul>
<li v-for="(value, index) in findElementById(dataDepartments, results.department_id)">
{{ index }} : {{ value }}
</li>
</ul>
</div>
</div>
<!-- End Department -->
<!-- Subject -->
<div>
<h1>Subject</h1>
<div v-if="results.subject_id > 0">
<ul>
<li v-for="(value, index) in findElementById(dataSubjects, results.subject_id)">
{{ index }} : {{ value }}
</li>
</ul>
</div>
</div>
<!-- End Subject -->
</div>
</template>
<script>
// import your select component
import SubjecttableSelect from './SubjecttableSelect';
export default {
components: {
// register the component
SubjecttableSelect,
},
props: {
dataDepartments: { type: Array, required: true },
dataSubjects:{ type: Array, required: true},
dataSubjecttable: {type: Array, required: true },
},
name: "Lessons",
data() {
return {
results: {
subject_id: 0,
department_id: 0,
},
}
},
methods: {
updateResults(data) {
this.results = data;
},
findElementById(element, id) {
return element.find(el => el.id === id);
}
},
}
</script>
<style scoped>
</style>
app.js
// register the new component
Vue.component('lessons', require('./components/Lessons.vue').default);
// subjecttable-select can now be imported within lessons
const app = new Vue({
el: '#app',
});
your.blade.php (please note the single quotes)
<lessons :data-subjecttable='#json($subjectslessons)'
:data-departments='#json($departments)'
:data-subjects='#json($subjects)'>
</lessons>

Resources