Hi i have a problem about select2 and livewire, after go to another page and back to dashboard the dropdown list of select2 dissapeared, i checked the source the list still on there and not loaded
<script>
$(document).ready(function() {
$('.live-search').select2({
placeholder: 'Search Services',
// allowClear: true,
});
$('.live-search').on('change', function(e) {
Livewire.emit('servicesId', e.target.value);
});
});
</script>
<div class="form-group" wire:ignore>
<label>Services :</label>
<select class="form-control live-search" wire:model='servicesId'>
#foreach ($data as $service)
<option value="{{ $service->id }}">{{ Str::ucfirst($service->service_name) }} -
Rp.{{ $service->price }}
</option>
#endforeach
</select>
<hr />
</div>
I'm having a difficult time getting Vue to work in a blade.php page I have in my laravel website.
Here is the blade page code:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght#400;600;700&display=swap" rel="stylesheet">
<!-- Custom css -->
<link href="{{ url('sass/custom.scss.css') }}" type="text/css" rel="stylesheet">
<!-- Fav icon -->
<link rel="icon" type="image/png" href="{{ url('omnisection.png') }}">
<!-- development version, includes helpful console warnings -->
<script src="{{ mix('/js/vue.js') }}"></script>
<script src="{{ mix('/js/app.js') }}"></script>
<script src="{{ mix('/js/RecordRTC.js') }}"></script>
<script src="{{ mix('/js/customrecrtc.js') }}"></script>
<!-- Styles -->
<style>
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}a{background-color:transparent}[hidden]{display:none}html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}*,:after,:before{box-sizing:border-box;border:0 solid #e2e8f0}a{color:inherit;text-decoration:inherit}svg,video{display:block;vertical-align:middle}video{max-width:100%;height:auto}.bg-white{--bg-opacity:1;background-color:#fff;background-color:rgba(255,255,255,var(--bg-opacity))}.bg-gray-100{--bg-opacity:1;background-color:#f7fafc;background-color:rgba(247,250,252,var(--bg-opacity))}.border-gray-200{--border-opacity:1;border-color:#edf2f7;border-color:rgba(237,242,247,var(--border-opacity))}.border-t{border-top-width:1px}.flex{display:flex}.grid{display:grid}.hidden{display:none}.items-center{align-items:center}.justify-center{justify-content:center}.font-semibold{font-weight:600}.h-5{height:1.25rem}.h-8{height:2rem}.h-16{height:4rem}.text-sm{font-size:.875rem}.text-lg{font-size:1.125rem}.leading-7{line-height:1.75rem}.mx-auto{margin-left:auto;margin-right:auto}.ml-1{margin-left:.25rem}.mt-2{margin-top:.5rem}.mr-2{margin-right:.5rem}.ml-2{margin-left:.5rem}.mt-4{margin-top:1rem}.ml-4{margin-left:1rem}.mt-8{margin-top:2rem}.ml-12{margin-left:3rem}.-mt-px{margin-top:-1px}.max-w-6xl{max-width:72rem}.min-h-screen{min-height:100vh}.overflow-hidden{overflow:hidden}.p-6{padding:1.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.pt-8{padding-top:2rem}.fixed{position:fixed}.relative{position:relative}.top-0{top:0}.right-0{right:0}.shadow{box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06)}.text-center{text-align:center}.text-gray-200{--text-opacity:1;color:#edf2f7;color:rgba(237,242,247,var(--text-opacity))}.text-gray-300{--text-opacity:1;color:#e2e8f0;color:rgba(226,232,240,var(--text-opacity))}.text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}.text-gray-500{--text-opacity:1;color:#a0aec0;color:rgba(160,174,192,var(--text-opacity))}.text-gray-600{--text-opacity:1;color:#718096;color:rgba(113,128,150,var(--text-opacity))}.text-gray-700{--text-opacity:1;color:#4a5568;color:rgba(74,85,104,var(--text-opacity))}.text-gray-900{--text-opacity:1;color:#1a202c;color:rgba(26,32,44,var(--text-opacity))}.underline{text-decoration:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.w-5{width:1.25rem}.w-8{width:2rem}.w-auto{width:auto}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}#media (min-width:640px){.sm\:rounded-lg{border-radius:.5rem}.sm\:block{display:block}.sm\:items-center{align-items:center}.sm\:justify-start{justify-content:flex-start}.sm\:justify-between{justify-content:space-between}.sm\:h-20{height:5rem}.sm\:ml-0{margin-left:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:pt-0{padding-top:0}.sm\:text-left{text-align:left}.sm\:text-right{text-align:right}}#media (min-width:768px){.md\:border-t-0{border-top-width:0}.md\:border-l{border-left-width:1px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}#media (min-width:1024px){.lg\:px-8{padding-left:2rem;padding-right:2rem}}#media (prefers-color-scheme:dark){.dark\:bg-gray-800{--bg-opacity:1;background-color:#2d3748;background-color:rgba(45,55,72,var(--bg-opacity))}.dark\:bg-gray-900{--bg-opacity:1;background-color:#1a202c;background-color:rgba(26,32,44,var(--bg-opacity))}.dark\:border-gray-700{--border-opacity:1;border-color:#4a5568;border-color:rgba(74,85,104,var(--border-opacity))}.dark\:text-white{--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity))}.dark\:text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}.dark\:text-gray-500{--tw-text-opacity:1;color:#6b7280;color:rgba(107,114,128,var(--tw-text-opacity))}}
</style>
<style>
body {
font-family: 'Nunito', sans-serif;
}
</style>
</head>
<body class="antialiased">
<div id="app">
#{{ message }}
</div>
<script>
var test = new Vue({
el: '#app',
data: {
message: 'hi'
}
});
</script>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="/"><img class="rounded-3" src="{{ url('omnisection(new).png') }}" style="width:172px;height:108px" /></a>
<button class="navbar-toggler brotoggle" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
#foreach($pages as $page)
<li class="nav-item">
<a href="{{ url($page['url']) }}">
<button class="btn btn-lg btn-outline-secondary brobutton" type="button">{{ $page['page_name'] }}</button>
</a>
</li>
#endforeach
</ul>
<form class="d-flex">
<input class="form-control me-2" type="search" placeholder="Search Requests" aria-label="Search">
<a href="{{ url('search') }}">
<button class="btn btn-outline-secondary brobutton" type="submit">Search</button>
</a>
</form>
</div>
</div>
</nav>
<div class="relative flex items-top justify-center bg-gray-100 dark:bg-gray-900 sm:items-center sm:pt-0">
#if (Route::has('login'))
<div class="hidden fixed top-0 right-0 px-6 py-4 sm:block">
#auth
Dashboard
#else
Log in
#if (Route::has('register'))
Register
#endif
#endauth
</div>
#endif
</div>
<!-- Fluid container -->
<div class="container-fluid mt-1">
<div class="row">
<div class="col fs-1 text-center">
Your Data
</div>
<div class="col fs-1 text-center border-start">
Other's Data
</div>
</div>
<div class="row">
<div class="col">
#guest
<a href="{{ url('login') }}">
<button type="button" class="btn rounded btn-primary btn-lg start-50 translate-middle-x position-relative" alt="login button">Log in</button>
</a>
#endguest
</div>
<div class="col fs-1 border-start text-center">
#guest
?
#endguest
</div>
</div>
<div class="row">
<div class="col">
#auth
<div class="input-group mb-3">
<input type="file" class="form-control mt-2" id="inputGroupFile02" data-bs-toggle="tooltip" data-bs-placement="top" title="Use this to upload a file">
<label class="input-group-text mt-2" for="inputGroupFile02">Upload</label>
</div>
#endauth
</div>
<div class="col border-end" id="rcrdplayer">
#auth
<button v-on:click="startrecord" type="button" class="rounded-circle button-rec btn-lg btn-secondary" id="btn-start-recording" alt="record audio button" data-bs-toggle="tooltip" data-bs-placement="top" title="Use this button to record audio">Rec</button>
<img src="video.svg" class="img-fluid custom-img-bg rounded" id="btn-start-recording" alt="record video button" height="75" width="75" data-bs-toggle="tooltip" data-bs-placement="top" title="Use this button to record video"/>
#endauth
</div>
<div class="col">
</div>
<div class="col">
</div>
</div>
<!-- Recorder -->
#auth
<div class="row">
<div class="col">
<select class="form-select form-select-sm media-resolutions">
<option value="default">Default resolutions</option>
<option value="1920x1080">1080p</option>
<option value="1280x720">720p</option>
<option value="640x480">480p</option>
<option value="3840x2160">4K Ultra HD (3840x2160)</option>
</select>
<select class="form-select form-select-sm media-framerates" aria-label=".form-select-sm example">
<option value="default">Default framerates</option>
<option value="5">5 fps</option>
<option value="15">15 fps</option>
<option value="24">24 fps</option>
<option value="30">30 fps</option>
<option value="60">60 fps</option>
</select>
<select class="form-select form-select-sm media-bitrates" aria-label=".form-select-sm example">
<option value="default">Default bitrates</option>
<option value="8000000000">1 GB bps</option>
<option value="800000000">100 MB bps</option>
<option value="8000000">1 MB bps</option>
<option value="800000">100 KB bps</option>
<option value="8000">1 KB bps</option>
<option value="800">100 Bytes bps</option>
</select>
</div>
<div class="col border-end">
</div>
</div>
#endauth
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
</body>
</html>
Here is the Webpack code:
const mix = require('laravel-mix');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel applications. By default, we are compiling the CSS
| file for the application as well as bundling up all the JS files.
|
*/
module.exports = {
mode: 'development'
}
mix.sass('resources/css/custom.scss','public/sass/custom.scss');
mix.js('node_modules/recordrtc/RecordRTC.js', 'public/js/RecordRTC.js');
mix.js('resources/js/customrecrtc.js', 'public/js/customrecrtc.js');
mix.js('resources/js/app.js', 'public/js').postCss('resources/css/app.css', 'public/css', [
require('postcss-import'),
require('tailwindcss'),
require('autoprefixer'),
]);
I've read and re-read the docs on the installation, then I found that I was in version 2.x, so I switched to version 3.x. All this to no avail. It works if I use the CDN method, and I am then able to run some vue code in the blade template. I really just wanted to have all my node modules linked to the page through NPM, otherwise I would just use the CDN method.
Update: I have added the Webpack and Blade code. Since I installed Vue 3 using
npm install vue#next
I can't find where to add Vue from my node modules. This is a new laravel project, using Laravel 8.x
https://laravel.com/docs/8.x/mix#working-with-scripts
As it says in the above link, since I'm using Webpack which compiles JS code. I found that I must import the specific node module. If you have programmed before, think of it as importing or including a file in Java, C++, Python, or what have you.
In my case I needed to realize that I not only had to import one module, but many. And then specifically use the same file I imported into to type the relevant code. I still can't type the JS into the .blade.php file, but this should work well enough.
This an example of my custom.js
import node_module1
import node module2
// code goes here
I want to when a user select a dropdown from the list, a group of subjects available for that grade must be displayed with checkboxes next to them
My controller
public function create()
{
$grades = Grade::with('subjects')->orderBy('slug', 'asc')->get();
return view('admin.users.create', compact( 'grades'));
}
Blade file
<div class="form-group">
<select id="grade" name="grade" class="form-control #error('grade') is-invalid #enderror" v-model="selectedSubjects">
<option value="">Choose a Grade...</option>
#foreach($grades as $grade)
<option value="{{ $grade->id }}" {{ old('grade', $grade) == $grade->name ? 'selected' : "" }}>{{ $grade->name }}</option>
#endforeach
</select>
</div>
<div class="custom-control custom-checkbox mt-2">
#foreach($grade->subjects as $subject)
<input type="checkbox" class="custom-control-input" id="{{$subject->slug}}" name="subjects[]" :value="selectedSubjects" />
<label class="custom-control-label" for="{{$subject->slug}}">{{$subject->name}}</label>
#endforeach
</div>
vue
<script>
window.addEventListener('load',function(){
var app = new Vue({
el: '#app',
data:{
selectedSubjects: {!! $grade->subjects->pluck('name') !!},
}
});
});
</script>
THIS IS IMPOSSIBLE... I GIVE UP
As per I have understood, you want to select grades from dropdown & show its corresponding checkbox as per subjects for the grades.
I would suggest to create a vue component for that lets say grades-component,
in your blade you can add,
<form action="" class="form-control">
#csrf
<grade-component :grades='#json($grades)'></grade-component>
</form>
here in blade, $grades is the object(or array) you are passing via compact. Basically it is to pass your data to the component, we will use that with help of props.
Now you can add your GradeComponent.vue in resources->js->components->GradeComponent.vue
GradeComponent.vue
<template>
<div class="container">
<select v-model="selected_grade" #change="onChange($event)">
<option v-for="grade in grading" :value="grade.slug">{{grade.name}}</option>
</select>
<div class="custom-control custom-checkbox mt-2" v-if="subjects !== null" v-for="subject in subjects">
<input type="checkbox" :id="subject.slug" :value="subject.slug"/>
<label :for="subject.slug">{{subject.name}}</label>
</div>
</div>
</template>
<script>
export default{
props: ['grades'],
data: function() {
return {
grading: this.grades,
selected_grade: null,
subjects : null
}
},
methods: {
onChange(event) {
this.grading.forEach((obj, index) => {
if (obj.slug === event.target.value){
this.subjects = obj.subjects;
}
})
}
}
}
</script>
Now finally you can add it in app.js
Vue.component('grade-component', require('./components/GradeComponent.vue').default);
Then compile your vuejs code, I would use npm run watch
A similar one but with fake data, you can see https://jsfiddle.net/bhucho/2yu4nmws/3/,
Am working on a Laravel 8 package that swaps the #TALL stack for what I call the #BALL stack, and its basically a Bootstrap, AlpineJs Laravel, Livewire stack. Bootstrap 5 is leaning towards utility classes and no longer makes use of JQuery which gives room for AlpineJs so I really don't see a lot of upsides with Tailwind, not to mention I've gotten really comfortable with Bootstrap which should be all that matters at the end right?
Now the problem is this, I've been able to make changes to a lot of the JetStream blade files and if youve install Jetstream then your familiar with this image:
(Yes!!!! Its the exact same thing but with Bootstrap!)
but one particular component has kept me up for days and its the Bootstrap Modal.
Whenever I call the Bootstrap modal Livewire requests seem to make the Modal itself disappear leaving just the backdrop, forcing a page request before anything else can be clicked.
The final request is never completed
I have no way to hold the modal until a confirmation request is loaded and then programmatically disable the modal when finished.
The exact place I have this problem is in the views/api/api-token-manager.blade which is added by Jetstream when you install the livewire stack. My files looks like so:
My views/api/api-token-manager.blade
<!-- API Token List -->
// Inside a x-jet-action-section component
<x-slot name="content">
<div class="space-y-6">
#foreach ($this->user->tokens->sortBy('name') as $token)
<div class="d-flex justify-content-between">
<div>
{{ $token->name }}
</div>
<div class="d-flex">
#if ($token->last_used_at)
<div class="text-sm text-muted">
Last used {{ $token->last_used_at->diffForHumans() }}
</div>
#endif
#if (Laravel\Jetstream\Jetstream::hasPermissions())
<button class="btn btn-link text-secondary" data-toggle="modal"
wire:click="manageApiTokenPermissions({{ $token->id }})"
data-target="#managingApiTokenPermissions-{{ $token->id }}">
Permissions
</button>
#endif
<button class="btn btn-link text-danger text-decoration-none"
data-toggle="modal"
data-target="#confirmApiTokenDeletion-{{ $token->id }}">
Delete
</button>
</div>
</div>
<!-- API Token Permissions Modal -->
<x-jet-dialog-modal id="managingApiTokenPermissions-{{ $token->id }}">
<x-slot name="title">
API Token Permissions
</x-slot>
<x-slot name="content">
<div class="mt-2 row">
#foreach (Laravel\Jetstream\Jetstream::$permissions as $permission)
<div class="col-6">
<div class="form-check">
<input class="form-check-input" type="checkbox" value="{{ $permission }}" wire:model.defer="updateApiTokenForm.permissions">
<label class="form-check-label">
{{ $permission }}
</label>
</div>
</div>
#endforeach
</div>
</x-slot>
<x-slot name="footer">
<x-jet-secondary-button data-dismiss="modal">
{{ __('Nevermind') }}
</x-jet-secondary-button>
<x-jet-button class="ml-2" wire:click="updateApiToken"
wire:click="$emit('updateApiToken', {{ $token->id }})"
data-dismiss="modal">
{{ __('Save') }}
</x-jet-button>
</x-slot>
</x-jet-dialog-modal>
#push('scripts')
<script>
Livewire.on('updateApiToken', id => {
#this.manageApiTokenPermissions(id)
#this.updateApiToken()
})
</script>
#endpush
<!-- Delete Token Confirmation Modal -->
<x-jet-confirmation-modal id="confirmApiTokenDeletion-{{ $token->id }}">
<x-slot name="title">
Delete API Token
</x-slot>
<x-slot name="content">
Are you sure you would like to delete this API token?
</x-slot>
<x-slot name="footer">
<x-jet-secondary-button data-dismiss="modal">
Nevermind
</x-jet-secondary-button>
<x-jet-danger-button class="ml-2"
wire:click="$emit('deleteApiToken', {{ $token->id }})"
data-dismiss="modal">
Delete
</x-jet-danger-button>
</x-slot>
</x-jet-confirmation-modal>
#push('scripts')
<script>
Livewire.on('deleteApiToken', id => {
#this.confirmApiTokenDeletion(id)
#this.deleteApiToken()
})
</script>
#endpush
#endforeach
</div>
</x-slot>
My x-jet-dialog-modal component
#props(['id' => null, 'maxWidth' => null])
<x-jet-modal :id="$id" :maxWidth="$maxWidth" {{ $attributes }}>
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">{{ $title }}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
{{ $content }}
</div>
<div class="modal-footer">
{{ $footer }}
</div>
</div>
</x-jet-modal>
My x-jet-modal component
#props(['id', 'maxWidth', 'modal' => false])
#php
$id = $id ?? md5($attributes->wire('model'));
switch ($maxWidth ?? '') {
case 'sm':
$maxWidth = ' modal-sm';
break;
case 'md':
$maxWidth = '';
break;
case 'lg':
$maxWidth = ' modal-lg';
break;
case 'xl':
$maxWidth = ' modal-xl';
break;
case '2xl':
default:
$maxWidth = '';
break;
}
#endphp
<!-- Modal -->
<div class="modal fade" tabindex="-1" id="{{ $id }}" aria-labelledby="{{ $id }}" aria-hidden="true">
<div class="modal-dialog{{ $maxWidth }}">
{{ $slot }}
</div>
</div>
I really don't want to make the change to Tailwind regardless of the hype so I would love any assistance the community can render.
To make a direct contribution to the project click here.
Thanks!!!
I was able to solve the above problem with Livewire Event. Its important to note that the reason for all this hassle was to create assets to replace Jetstream assets without affecting the business logic i.e. MODEL and CONTROLLER.
Here is what my solution looks like:
<div class="mt-3">
<x-jet-danger-button wire:click="$emit('confirmingUserDeletion')"
wire:loading.attr="disabled">
Delete Account
</x-jet-danger-button>
</div>
<!-- Delete User Confirmation Modal -->
<x-jet-dialog-modal id="confirmingUserDeletionModal">
<x-slot name="title">
Delete Account
</x-slot>
<x-slot name="content">
Are you sure you want to delete your account? Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.
<div class="mt-4 w-75" x-data="{}" x-on:confirming-delete-user.window="setTimeout(() => $refs.password.focus(), 250)">
<x-jet-input type="password" class="{{ $errors->has('password') ? 'is-invalid' : '' }}" placeholder="Password"
x-ref="password"
wire:model.defer="password"
wire:keydown.enter="deleteUser" />
<x-jet-input-error for="password" />
</div>
</x-slot>
<x-slot name="footer">
<x-jet-secondary-button wire:click="$toggle('confirmingUserDeletion')"
wire:loading.attr="disabled"
data-dismiss="modal">
Nevermind
</x-jet-secondary-button>
<x-jet-danger-button wire:click="deleteUser" wire:loading.attr="disabled">
Delete Account
</x-jet-danger-button>
</x-slot>
</x-jet-dialog-modal>
#push('scripts')
<script>
Livewire.on('confirmingUserDeletion', () => {
#this.confirmUserDeletion()
new Bootstrap.Modal(document.getElementById('confirmingUserDeletionModal')).toggle()
})
</script>
#endpush
I want to pass selected value from dropdown to be passed throw routing from the same blade file
Here is my blade code :
<div class="form-group col-md-2">
<label>#lang('site.son')</label>
#if(Auth::user()->shortsign == '--')
<select class="select2-size-lg form-control border-primary" style="width: 100%;" name="sign">
#foreach ($users as $user)
<option value="{{ $user->shortsign }}">{{ $user->shortsign }}</option>
#endforeach
</select>
#else
<select class="select2-size-lg form-control border-primary" style="width: 100%;" name="sign" readonly>
<option value="{{ Auth::user()->shortsign }}">{{ Auth::user()->shortsign }}</option>
</select>
#endif
</div>
<div class="form-actions right">
<i class="la la-search" aria-hidden="true"></i> #lang('site.search')
</div>
Now the code iam using pass the last value from database not selected value
you can try this by giving id to your anchor tag
<script type="text/javascript">
$('.select2-size-lg').change(function () {
var id = $(this).val();
document.getElementById("abc").href="{{ url('/salereports/report/' . id) }}";
});
</script>