Orderby Desc in Eloquent Laravel for related table - laravel

I get property 'image' of non-object error while trying to rearrange the order by which the data of two tables are being retrieved.
Here is my code for userController#index
$users = User::orderBy('id', 'desc')->with('profile')->paginate(2);
return view('multiauth::admin.user')->with('users', $users);
Code for admin.user view
#foreach ($users as $user)
<tr>
<td class="sort-image">{{$user->first_name}}</td>
<td class="sort-name">{{$user->last_name}}</td>
<td class="sort-name">{{$user->email}}</td>
<td class="sort-name">{{$user->account_type}}</td>
<td class="sort-name">{{$user->account_status}}</td>
<td class="sort-phone">{{$user->profile->image}}</td>
<td class="sort-email">{{$user->profile->business_name}}</td>
<td class="sort-address">{{$user->profile->address}}</td>
<td class="sort-city">{{$user->profile->city}}</td>
<td class="sort-state">{{$user->profile->state}}</td>
<td class="sort-country">{{$user->profile->country}}</td>
<td class="sort-zip">{{$user->profile->postal}}</td>
<td class="sort-date" data-date="1628071164">{{$user->profile->dob}}</td>
<td class="sort-phone">{{$user->profile->phone}}</td>
<td class="sort-name">{{$user->profile->facebook}}</td>
<td class="sort-name">{{$user->profile->linkedin}}</td>
<td class="sort-name">{{$user->profile->twitter}}</td>
<td class="sort-name">{{$user->profile->instagram}}</td>
<td class="sort-name">{{$user->profile->website}}</td>
<td> <a href="#" class="btn btn-white"><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-pencil" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M4 20h4l10.5 -10.5a1.5 1.5 0 0 0 -4 -4l-10.5 10.5v4"></path>
<line x1="13.5" y1="6.5" x2="17.5" y2="10.5"></line>
</svg></a>
</td>
<td> <a href="#" class="btn btn-white"><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-trash" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<line x1="4" y1="7" x2="20" y2="7"></line>
<line x1="10" y1="11" x2="10" y2="17"></line>
<line x1="14" y1="11" x2="14" y2="17"></line>
<path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12"></path>
<path d="M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3"></path>
</svg></a>
</td>
</tr>
#endforeach
Code for User Model
public function profile()
{
return $this->hasOne(Profile::class);
}
Code for Profile Model
public function user()
{
return $this->belongsTo(User::class);
}
I'm using laravel 8. What I'm I missing please?

You are getting that error because if a user does not belong to a profile then...
$user->profile === null;
There by $user->profile->image will throw an error.
There are two things you can do.
PHP8 has a feature which is the question mark operator.
$user?->profile?->image
The question mark operator is syntax that is basically the same as
isset($user->profile) && isset($user->profile->image)
The other thing you can do is to add a constraint to your query that will only return users that belong to a profile.
User::whereHas('profile')->with('profile')->get();

I found out it's not a syntax error, that the user records in the database are not properly related to the profile. i.e Userid column in the Profiles table is not related to the id in the Users table.

Related

Metronic HTML template: Button menu in ajax datatable does not show menu items

Metronic HTML template: I'm really struggling to make button menu items work when they are part of a datatable generated via ajax. Meaning that the column is created using the render method within the datatable function (example below). Buttom menu appears in the column, but when clicked, no menu items appear below the button. Anyone had this issue and had it resolved?
{
targets: -1,
data: null,
orderable: false,
className: 'text-end',
render: function (data, type, row) {
return `
<a href="#" class="btn btn-light btn-active-light-primary btn-sm" data-kt-menu-trigger="click" data-kt-menu-placement="bottom-end" data-kt-menu-flip="top-end">
Actions
<span class="svg-icon svg-icon-5 m-0">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24px" height="24px" viewBox="0 0 24 24" version="1.1">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<polygon points="0 0 24 0 24 24 0 24"></polygon>
<path d="M6.70710678,15.7071068 C6.31658249,16.0976311 5.68341751,16.0976311 5.29289322,15.7071068 C4.90236893,15.3165825 4.90236893,14.6834175 5.29289322,14.2928932 L11.2928932,8.29289322 C11.6714722,7.91431428 12.2810586,7.90106866 12.6757246,8.26284586 L18.6757246,13.7628459 C19.0828436,14.1360383 19.1103465,14.7686056 18.7371541,15.1757246 C18.3639617,15.5828436 17.7313944,15.6103465 17.3242754,15.2371541 L12.0300757,10.3841378 L6.70710678,15.7071068 Z" fill="#000000" fill-rule="nonzero" transform="translate(12.000003, 11.999999) rotate(-180.000000) translate(-12.000003, -11.999999)"></path>
</g>
</svg>
</span>
</a>
<!--begin::Menu-->
<div class="menu menu-sub menu-sub-dropdown menu-column menu-rounded menu-gray-600 menu-state-bg-light-primary fw-bold fs-7 w-125px py-4" data-kt-menu="true">
<!--begin::Menu item-->
<div class="menu-item px-3">
<a href="#" class="menu-link px-3" data-kt-docs-table-filter="edit_row">
Edit
</a>
</div>
<!--end::Menu item-->
<!--begin::Menu item-->
<div class="menu-item px-3">
<a href="#" class="menu-link px-3" data-kt-docs-table-filter="delete_row">
Delete
</a>
</div>
<!--end::Menu item-->
</div>
<!--end::Menu-->
`;
}
}

no sound in modern browser

i have code index.html
<!-- play and stop button -->
<div x-data="playaudio()" class="grid place-content-center m-14">
<button #keydown.tab="playAndStop" #click="playAndStop" type="button"
class="relative rounded-xl group cursor-pointer focus:outline-none focus:ring focus:ring-[#1F89AE]">
<div class="absolute inset-0 flex items-center justify-center p-8">
<div class="w-full h-full transition duration-300 ease-in-out bg-cyan-500 filter group-hover:blur-2xl">
</div>
</div>
<div
class="absolute inset-0 flex items-center justify-center transition duration-200 ease-in-out bg-black rounded-xl bg-opacity-30 group-hover:bg-opacity-20">
<div x-show="!currentlyPlaying" class="bg-black bg-opacity-50 rounded-full p-0.5">
<!-- icon play -->
<svg
class="w-20 h-20 text-white text-opacity-0 transition duration-150 ease-in-out hover:text-opacity-20"
viewBox="0 0 284 284" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path
d="M184.197 129.243L135.177 96.5521C132.865 95.01 130.178 94.1249 127.403 93.9915C124.628 93.8581 121.868 94.4813 119.419 95.7946C116.971 97.1079 114.925 99.0619 113.501 101.448C112.077 103.834 111.327 106.562 111.333 109.34V174.706C111.333 177.482 112.086 180.206 113.513 182.588C114.939 184.969 116.985 186.919 119.433 188.228C121.881 189.538 124.638 190.158 127.411 190.024C130.183 189.889 132.867 189.004 135.177 187.463L184.197 154.773C186.297 153.373 188.019 151.475 189.21 149.25C190.401 147.025 191.024 144.54 191.024 142.015C191.024 139.491 190.401 137.006 189.21 134.781C188.019 132.555 186.297 130.658 184.197 129.258V129.243Z"
fill="white"></path>
<path
d="M280 142C280 160.122 276.431 178.067 269.495 194.81C262.56 211.553 252.395 226.766 239.581 239.581C226.766 252.395 211.553 262.56 194.81 269.495C178.067 276.431 160.122 280 142 280C123.878 280 105.933 276.431 89.1897 269.495C72.4468 262.56 57.2337 252.395 44.4193 239.581C31.6048 226.766 21.4398 211.553 14.5046 194.81C7.56947 178.067 4 160.122 4 142C4 105.4 18.5392 70.2993 44.4193 44.4193C70.2993 18.5392 105.4 4 142 4C178.6 4 213.701 18.5392 239.581 44.4193C265.461 70.2993 280 105.4 280 142Z"
stroke="white" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
</div>
<div x-show="currentlyPlaying" class="bg-black bg-opacity-50 rounded-full p-0.5">
<!-- icon stop -->
<svg xmlns="http://www.w3.org/2000/svg"
class="w-20 h-20 text-white text-opacity-0 transition duration-150 ease-in-out hover:text-opacity-20"
viewBox="0 0 20 20" fill="white">
<path fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zM8 7a1 1 0 00-1 1v4a1 1 0 001 1h4a1 1 0 001-1V8a1 1 0 00-1-1H8z"
clip-rule="evenodd" />
</svg>
</div>
</div>
</button>
<audio x-ref="audio" preload="none" autoplay="autoplay">
<source src="http://119.235.249.201:8872/;" type="audio/mpeg" />
</audio>
</div>
and code js is
function playaudio() {
return {
currentlyPlaying: false,
//play and stop the audio
playAndStop() {
if (this.currentlyPlaying) {
this.$refs.audio.pause();
this.$refs.audio.currentTime = 0;
this.currentlyPlaying = false;
} else {
this.$refs.audio.play();
this.currentlyPlaying = true;
}
},
};
}
I uploaded the file but it worked but when we play the audio stream it doesn't work in modern browsers.
this is url my website : https://suaranabawiy.netlify.app/radio
I checked with developer tools for an error : Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause()
can you help me to make my code work in the latest browser ?
i use tailwindcss and alpine.js
The problem is with the audio file you're loading. You're requesting an HTML page and placing it inside the audio tag. The request fails but the status was updated to playing. When you click it again you get the error message you described.
Audio tag must have a valid source. To learn more about the supported sources, check here.
Again, you cannot embed a service for audio streaming as an audio file.

Reusable nav link with icon component in Laravel Blade

I'm working on an admin interface using Laravel, AlpineJS and Tailwind CSS and I'm currently building the sidebar which can have many links, each link having an icon. I created a general x-sidebar-link component and a distinct component for each icon, but I'm not really fond of the approach because I can't really use those icon components elsewhere.
Is there a better way to build this in order to ensure reusability of the icon component? Like to be able to pass in classes for the active state as well, if needed.
The x-sidebar-link component:
#props(['active'])
#php
$classes = ($active ?? false)
? 'bg-gray-100 text-gray-900 group flex items-center px-2 py-2 text-sm font-medium rounded-md'
: 'text-gray-600 hover:bg-gray-50 hover:text-gray-900 group flex items-center px-2 py-2 text-sm font-medium rounded-md';
#endphp
<a {{ $attributes->merge(['href' => '#', 'class' => $classes]) }}>
{{ $slot }}
</a>
The x-icons.dashboard component:
#aware(['active' => false])
#php
$classes = ($active ?? false)
? 'text-gray-500 mr-3 flex-shrink-0 h-6 w-6'
: 'text-gray-400 group-hover:text-gray-500 mr-3 flex-shrink-0 h-6 w-6';
#endphp
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"
aria-hidden="true" {{ $attributes->merge(['class' => $classes]) }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
</svg>
The way I'm using these is as following:
<nav>
<x-sidebar-link :href="route('dashboard')" :active="request()->routeIs('dashboard')">
<x-icons.dashboard />
Dashboard
</x-sidebar-link>
<x-sidebar-link :href="route('profile')" :active="request()->routeIs('profile')">
<x-icons.profile />
Profile
</x-sidebar-link>
...
</nav>

set dark mode using Laravel Vue3 e Intertiajs

I'm using the larastarters kit (https://github.com/LaravelDaily/Larastarters) as a side project to practice with Intertia, Vue and tailwindcss.
I'd like to set dark mode if the user clicks on a button starting with the default media preference.
I use Vuex to read the state from localstorage, everything seems to work, I can successfully set the class dark to the container, but nothing happens, whereas if I bind a single class eg bg-gray-800 the class gets applied.
I'm missing something but I can't figure it out.
Here's the store
import { createStore } from 'vuex'
import { getThemeFromLocalStorage, setThemeToLocalStorage } from '../utils/index.js'
// Create a new store instance.
export default createStore({
state() {
return {
darkTheme: getThemeFromLocalStorage(),
}
},
mutations: {
toggleTheme(state) {
state.darkTheme = !state.darkTheme;
setThemeToLocalStorage(state.darkTheme);
}
}
});
the component:
<template>
<button
class="rounded-md focus:outline-none focus:shadow-outline-purple"
#click="toggleTheme"
aria-label="Toggle color mode"
>
<template v-if="!dark">
<svg
class="w-5 h-5"
aria-hidden="true"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"
></path>
</svg>
</template>
<template v-if="dark">
<svg
class="w-5 h-5"
aria-hidden="true"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fill-rule="evenodd"
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
clip-rule="evenodd"
></path>
</svg>
</template>
</button>
</template>
<script>
export default {
computed: {
dark: function () {
return this.$store.state.darkTheme;
},
},
methods: {
toggleTheme: function () {
this.$store.commit("toggleTheme");
console.log(this.$store.state.darkTheme);
console.log(document.documentElement);
},
},
};
</script>
and the page I want to change color:
<template>
<Head title="Welcome" />
<div :class="{ dark: isDark }">
<div
class="relative flex justify-center min-h-screen bg-gray-100 dark:bg-gray-800 items-top sm:items-center sm:pt-0"
>
<div
v-if="canLogin"
class="fixed top-0 right-0 hidden px-6 py-4 sm:block"
>
<ThemeToggler></ThemeToggler>
<Link
v-if="$page.props.auth.user"
:href="route(routeBasePath + 'dashboard')"
class="text-sm text-gray-700 underline dark:text-purple-600"
>Dashboard
</Link>
<template v-else>
<Link :href="route('login')" class="text-sm text-gray-700 underline">
Log in
</Link>
<Link
v-if="canRegister"
:href="route('register')"
class="ml-4 text-sm text-gray-700 underline"
>
Register
</Link>
</template>
</div>
<div class="max-w-6xl mx-auto sm:px-6 lg:px-8">
<div class="flex justify-center pt-8 sm:justify-start sm:pt-0">
<svg
viewBox="0 0 651 192"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="w-auto h-16 text-gray-700 sm:h-20"
>
<g clip-path="url(#clip0)" fill="#EF3B2D">
<path
d="M248.032 44.676h-16.466v100.23h47.394v-14.748h-30.928V44.676zM337.091 87.202c-2.101-3.341-5.083-5.965-8.949-7.875-3.865-1.909-7.756-2.864-11.669-2.864-5.062 0-9.69.931-13.89 2.792-4.201 1.861-7.804 4.417-10.811 7.661-3.007 3.246-5.347 6.993-7.016 11.239-1.672 4.249-2.506 8.713-2.506 13.389 0 4.774.834 9.26 2.506 13.459 1.669 4.202 4.009 7.925 7.016 11.169 3.007 3.246 6.609 5.799 10.811 7.66 4.199 1.861 8.828 2.792 13.89 2.792 3.913 0 7.804-.955 11.669-2.863 3.866-1.908 6.849-4.533 8.949-7.875v9.021h15.607V78.182h-15.607v9.02zm-1.431 32.503c-.955 2.578-2.291 4.821-4.009 6.73-1.719 1.91-3.795 3.437-6.229 4.582-2.435 1.146-5.133 1.718-8.091 1.718-2.96 0-5.633-.572-8.019-1.718-2.387-1.146-4.438-2.672-6.156-4.582-1.719-1.909-3.032-4.152-3.938-6.73-.909-2.577-1.36-5.298-1.36-8.161 0-2.864.451-5.585 1.36-8.162.905-2.577 2.219-4.819 3.938-6.729 1.718-1.908 3.77-3.437 6.156-4.582 2.386-1.146 5.059-1.718 8.019-1.718 2.958 0 5.656.572 8.091 1.718 2.434 1.146 4.51 2.674 6.229 4.582 1.718 1.91 3.054 4.152 4.009 6.729.953 2.577 1.432 5.298 1.432 8.162-.001 2.863-.479 5.584-1.432 8.161zM463.954 87.202c-2.101-3.341-5.083-5.965-8.949-7.875-3.865-1.909-7.756-2.864-11.669-2.864-5.062 0-9.69.931-13.89 2.792-4.201 1.861-7.804 4.417-10.811 7.661-3.007 3.246-5.347 6.993-7.016 11.239-1.672 4.249-2.506 8.713-2.506 13.389 0 4.774.834 9.26 2.506 13.459 1.669 4.202 4.009 7.925 7.016 11.169 3.007 3.246 6.609 5.799 10.811 7.66 4.199 1.861 8.828 2.792 13.89 2.792 3.913 0 7.804-.955 11.669-2.863 3.866-1.908 6.849-4.533 8.949-7.875v9.021h15.607V78.182h-15.607v9.02zm-1.432 32.503c-.955 2.578-2.291 4.821-4.009 6.73-1.719 1.91-3.795 3.437-6.229 4.582-2.435 1.146-5.133 1.718-8.091 1.718-2.96 0-5.633-.572-8.019-1.718-2.387-1.146-4.438-2.672-6.156-4.582-1.719-1.909-3.032-4.152-3.938-6.73-.909-2.577-1.36-5.298-1.36-8.161 0-2.864.451-5.585 1.36-8.162.905-2.577 2.219-4.819 3.938-6.729 1.718-1.908 3.77-3.437 6.156-4.582 2.386-1.146 5.059-1.718 8.019-1.718 2.958 0 5.656.572 8.091 1.718 2.434 1.146 4.51 2.674 6.229 4.582 1.718 1.91 3.054 4.152 4.009 6.729.953 2.577 1.432 5.298 1.432 8.162 0 2.863-.479 5.584-1.432 8.161zM650.772 44.676h-15.606v100.23h15.606V44.676zM365.013 144.906h15.607V93.538h26.776V78.182h-42.383v66.724zM542.133 78.182l-19.616 51.096-19.616-51.096h-15.808l25.617 66.724h19.614l25.617-66.724h-15.808zM591.98 76.466c-19.112 0-34.239 15.706-34.239 35.079 0 21.416 14.641 35.079 36.239 35.079 12.088 0 19.806-4.622 29.234-14.688l-10.544-8.158c-.006.008-7.958 10.449-19.832 10.449-13.802 0-19.612-11.127-19.612-16.884h51.777c2.72-22.043-11.772-40.877-33.023-40.877zm-18.713 29.28c.12-1.284 1.917-16.884 18.589-16.884 16.671 0 18.697 15.598 18.813 16.884h-37.402zM184.068 43.892c-.024-.088-.073-.165-.104-.25-.058-.157-.108-.316-.191-.46-.056-.097-.137-.176-.203-.265-.087-.117-.161-.242-.265-.345-.085-.086-.194-.148-.29-.223-.109-.085-.206-.182-.327-.252l-.002-.001-.002-.002-35.648-20.524a2.971 2.971 0 00-2.964 0l-35.647 20.522-.002.002-.002.001c-.121.07-.219.167-.327.252-.096.075-.205.138-.29.223-.103.103-.178.228-.265.345-.066.089-.147.169-.203.265-.083.144-.133.304-.191.46-.031.085-.08.162-.104.25-.067.249-.103.51-.103.776v38.979l-29.706 17.103V24.493a3 3 0 00-.103-.776c-.024-.088-.073-.165-.104-.25-.058-.157-.108-.316-.191-.46-.056-.097-.137-.176-.203-.265-.087-.117-.161-.242-.265-.345-.085-.086-.194-.148-.29-.223-.109-.085-.206-.182-.327-.252l-.002-.001-.002-.002L40.098 1.396a2.971 2.971 0 00-2.964 0L1.487 21.919l-.002.002-.002.001c-.121.07-.219.167-.327.252-.096.075-.205.138-.29.223-.103.103-.178.228-.265.345-.066.089-.147.169-.203.265-.083.144-.133.304-.191.46-.031.085-.08.162-.104.25-.067.249-.103.51-.103.776v122.09c0 1.063.568 2.044 1.489 2.575l71.293 41.045c.156.089.324.143.49.202.078.028.15.074.23.095a2.98 2.98 0 001.524 0c.069-.018.132-.059.2-.083.176-.061.354-.119.519-.214l71.293-41.045a2.971 2.971 0 001.489-2.575v-38.979l34.158-19.666a2.971 2.971 0 001.489-2.575V44.666a3.075 3.075 0 00-.106-.774zM74.255 143.167l-29.648-16.779 31.136-17.926.001-.001 34.164-19.669 29.674 17.084-21.772 12.428-43.555 24.863zm68.329-76.259v33.841l-12.475-7.182-17.231-9.92V49.806l12.475 7.182 17.231 9.92zm2.97-39.335l29.693 17.095-29.693 17.095-29.693-17.095 29.693-17.095zM54.06 114.089l-12.475 7.182V46.733l17.231-9.92 12.475-7.182v74.537l-17.231 9.921zM38.614 7.398l29.693 17.095-29.693 17.095L8.921 24.493 38.614 7.398zM5.938 29.632l12.475 7.182 17.231 9.92v79.676l.001.005-.001.006c0 .114.032.221.045.333.017.146.021.294.059.434l.002.007c.032.117.094.222.14.334.051.124.088.255.156.371a.036.036 0 00.004.009c.061.105.149.191.222.288.081.105.149.22.244.314l.008.01c.084.083.19.142.284.215.106.083.202.178.32.247l.013.005.011.008 34.139 19.321v34.175L5.939 144.867V29.632h-.001zm136.646 115.235l-65.352 37.625V148.31l48.399-27.628 16.953-9.677v33.862zm35.646-61.22l-29.706 17.102V66.908l17.231-9.92 12.475-7.182v33.841z"
/>
</g>
</svg>
</div>
<div
class="mt-8 overflow-hidden bg-white shadow dark:bg-gray-800 sm:rounded-lg"
>
<div class="grid grid-cols-1 md:grid-cols-2">
<div class="p-6">
<div class="flex items-center">
<svg
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
class="w-8 h-8 text-gray-500"
>
<path
d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"
></path>
</svg>
<div class="ml-4 text-lg font-semibold leading-7">
<a
href="https://laravel.com/docs"
class="text-gray-900 underline dark:text-white"
>Documentation</a
>
</div>
</div>
<div class="ml-12">
<div class="mt-2 text-sm text-gray-600 dark:text-gray-400">
Laravel has wonderful, thorough documentation covering every
aspect of the framework. Whether you are new to the framework
or have previous experience with Laravel, we recommend reading
all of the documentation from beginning to end.
</div>
</div>
</div>
<div
class="p-6 border-t border-gray-200 dark:border-gray-700 md:border-t-0 md:border-l"
>
<div class="flex items-center">
<svg
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
class="w-8 h-8 text-gray-500"
>
<path
d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z"
></path>
<path d="M15 13a3 3 0 11-6 0 3 3 0 016 0z"></path>
</svg>
<div class="ml-4 text-lg font-semibold leading-7">
<a
href="https://laracasts.com"
class="text-gray-900 underline dark:text-white"
>Laracasts</a
>
</div>
</div>
<div class="ml-12">
<div class="mt-2 text-sm text-gray-600 dark:text-gray-400">
Laracasts offers thousands of video tutorials on Laravel, PHP,
and JavaScript development. Check them out, see for yourself,
and massively level up your development skills in the process.
</div>
</div>
</div>
<div class="p-6 border-t border-gray-200 dark:border-gray-700">
<div class="flex items-center">
<svg
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
class="w-8 h-8 text-gray-500"
>
<path
d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z"
></path>
</svg>
<div class="ml-4 text-lg font-semibold leading-7">
<a
href="https://laravel-news.com/"
class="text-gray-900 underline dark:text-white"
>Laravel News</a
>
</div>
</div>
<div class="ml-12">
<div class="mt-2 text-sm text-gray-600 dark:text-gray-400">
Laravel News is a community driven portal and newsletter
aggregating all of the latest and most important news in the
Laravel ecosystem, including new package releases and
tutorials.
</div>
</div>
</div>
<div
class="p-6 border-t border-gray-200 dark:border-gray-700 md:border-l"
>
<div class="flex items-center">
<svg
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
class="w-8 h-8 text-gray-500"
>
<path
d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
></path>
</svg>
<div
class="ml-4 text-lg font-semibold leading-7 text-gray-900 dark:text-white"
>
Vibrant Ecosystem
</div>
</div>
<div class="ml-12">
<div class="mt-2 text-sm text-gray-600 dark:text-gray-400">
Laravel's robust library of first-party tools and libraries,
such as
<a href="https://forge.laravel.com" class="underline">Forge</a
>,
<a href="https://vapor.laravel.com" class="underline">Vapor</a
>,
Nova,
and
Envoyer
help you take your projects to the next level. Pair them with
powerful open source libraries like
<a href="https://laravel.com/docs/billing" class="underline"
>Cashier</a
>,
<a href="https://laravel.com/docs/dusk" class="underline"
>Dusk</a
>,
<a
href="https://laravel.com/docs/broadcasting"
class="underline"
>Echo</a
>,
<a href="https://laravel.com/docs/horizon" class="underline"
>Horizon</a
>,
<a href="https://laravel.com/docs/sanctum" class="underline"
>Sanctum</a
>,
<a href="https://laravel.com/docs/telescope" class="underline"
>Telescope</a
>, and more.
</div>
</div>
</div>
</div>
</div>
<div
class="flex justify-center mt-4 sm:items-center sm:justify-between"
>
<div class="text-sm text-center text-gray-500 sm:text-left">
<div class="flex items-center">
<svg
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
stroke="currentColor"
class="w-5 h-5 -mt-px text-gray-400"
>
<path
d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z"
></path>
</svg>
<a href="https://laravel.bigcartel.com" class="ml-1 underline">
Shop
</a>
<svg
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
class="w-5 h-5 ml-4 -mt-px text-gray-400"
>
<path
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
></path>
</svg>
<a
href="https://github.com/sponsors/taylorotwell"
class="ml-1 underline"
>
Sponsor
</a>
</div>
</div>
<div
class="ml-4 text-sm text-center text-gray-500 sm:text-right sm:ml-0"
>
Laravel v{{ laravelVersion }} (PHP v{{ phpVersion }})
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.bg-gray-100 {
background-color: #f7fafc;
background-color: rgba(247, 250, 252, var(--tw-bg-opacity));
}
.border-gray-200 {
border-color: #edf2f7;
border-color: rgba(237, 242, 247, var(--tw-border-opacity));
}
.text-gray-400 {
color: #cbd5e0;
color: rgba(203, 213, 224, var(--tw-text-opacity));
}
.text-gray-500 {
color: #a0aec0;
color: rgba(160, 174, 192, var(--tw-text-opacity));
}
.text-gray-600 {
color: #718096;
color: rgba(113, 128, 150, var(--tw-text-opacity));
}
.text-gray-700 {
color: #4a5568;
color: rgba(74, 85, 104, var(--tw-text-opacity));
}
.text-gray-900 {
color: #1a202c;
color: rgba(26, 32, 44, var(--tw-text-opacity));
}
#media (prefers-color-scheme: dark) {
.dark\:bg-gray-800 {
background-color: #2d3748;
background-color: rgba(45, 55, 72, var(--tw-bg-opacity));
}
.dark\:bg-gray-900 {
background-color: #1a202c;
background-color: rgba(26, 32, 44, var(--tw-bg-opacity));
}
.dark\:border-gray-700 {
border-color: #4a5568;
border-color: rgba(74, 85, 104, var(--tw-border-opacity));
}
.dark\:text-white {
color: #fff;
color: rgba(255, 255, 255, var(--tw-text-opacity));
}
.dark\:text-gray-400 {
color: #cbd5e0;
color: rgba(203, 213, 224, var(--tw-text-opacity));
}
}
</style>
<script>
import { Head, Link } from "#inertiajs/inertia-vue3";
import ThemeToggler from "../Components/ThemeToggler.vue";
export default {
components: {
Head,
Link,
ThemeToggler,
},
props: {
canLogin: Boolean,
canRegister: Boolean,
laravelVersion: String,
phpVersion: String,
},
computed: {
routeBasePath() {
return this.$page.props.auth.routeBasePath;
},
isDark: function () {
return this.$store.state.darkTheme;
},
},
};
</script>
Thanks
I also had this inconvenience and this is how I solved it, without using "vuex"
Define the reactive variable "isDark", for this you have to import the dependencies
import { reactive, computed, ref } from "vue";
const isDark = ref();
Then I evaluate if it finds the dark mode in the local storage, if it exists I assign the value true to the isDark variable:
isDark.value = localStorage.getItem("darkMode") == "true";
Then create a method to evaluate whether the value found in local storage is true or false
function toggleDarkMode() {
isDark.value = !isDark.value;
localStorage.setItem("darkMode", isDark.value);
}
Reference the class: If "isDark" is true then add the class "dark" . Ex:
<body :class="{ dark: isDark }" class="flex flex-col h-screen bg-gray-100 dark: bg-gray-800">
Create a button or a switch and place the "toogleDarkMode()" function in the click method. Ex:
<button #click="toggleDarkMode">Light|Dark :)</button>
Done!
Note: Don't forget to put darkMode: class in tailwind.config.js file
Reference: https://tailwindcss.com/docs/dark-mode

validation using ajax in struts2

I used ajax validation to validate the following
<tr>
<td width="20" style='color: red'>
<img src="images/icon-star.png" width="16" height="16" />
</td>
<td id="lblCustomBillNo" style="width: 15%" class="searchCriteriaCellLbl">
The custom Bill Number
</td>
<td width="5" class="searchCriteriaCellLbl">:</td>
<td class="searchCriteriaCellVal">
<s:textfield id="customBillNo" name="customBillNo" size="20" maxlength="24" style="width: 200px" />
</td>
<td class="errorFlag" style="color: red" valign="middle">
<s:fielderror fieldName="customBillNo" />
</td>
</tr>
<tr>
<td width="20" style='color: red'>
<img src="images/icon-star.png" width="16" height="16" />
</td>
<td id="lblBillNo" style="width: 15%" class="searchCriteriaCellLbl">
<s:property value="%{getText('billNo')}" />
</td>
<td width="5" class="searchCriteriaCellLbl">:
</td>
<td class="searchCriteriaCellVal">
<s:textfield label="billNo" id="billNo" name="billNo" size="20" maxlength="24" style="width: 200px" />
</td>
<td class="errorFlag" style="color: red" valign="middle">
<s:fielderror fieldName="billNo" />
</td>
</tr>
<tr>
<td width="20" style='color: red'>
<img src="images/icon-star.png" width="16" height="16" />
</td>
<td id="lblCarrierNo" style="width: 15%" class="searchCriteriaCellLbl">
The carrier Number
</td>
<td width="5" class="searchCriteriaCellLbl">:
</td>
<td class="searchCriteriaCellVal">
<s:textfield label="carrierNo" id="carrierNo" name="carrierNo" size="20" maxlength="24" style="width: 200px" />
</td>
<td class="errorFlag" style="color: red" valign="middle">
<s:fielderror fieldName="carrierNo" />
</td>
</tr>
I use the following internationalization for errors in golbal i18n file
errors.required=${getText(fieldName)} requireddd
and this validation file
<validators>
<field name="customBillNo">
<field-validator type="requiredstring" short-circuit="true">
<param name="trim">true</param>
<message key="errors.required" />
</field-validator>
</field>
<field name="billNo">
<field-validator type="required" short-circuit="true">
<message key="errors.required" />
</field-validator>
</field>
<field name="carrierNo">
<field-validator type="required" short-circuit="true">
<message key="errors.required" />
</field-validator>
</field>
</validators>
and i put this javascript to use ajax validation
function validate(){
//document.all.loading.style.display = 'block';
var searchUrl = 'AddEnteringApproval_approval';
var params = '';
var elemArray = document.mainForm.elements;
for (var i = 0; i < elemArray.length;i++)
{
var element = elemArray[i];
var elementName= element.name;
if(elementName=='formAction')
continue;
params += '&' + elementName+'='+ encodeURIComponent(element.value);
}
params += '&struts.enableJSONValidation=true&struts.validateOnly=true';
createXmlHttpObject(); // this is my function that prepare ajax
sendRequestPost(http_request,searchUrl,false,params);
postValidation();
}
function postValidation() {
var form = $('#mainForm');
var text = http_request.responseText;
//clear previous validation errors, if any
StrutsUtils.clearValidationErrors(form);
alert(text)
//get errors from response
//var text = request.responseText;
var errorsObject = StrutsUtils.getValidationErrors(text);
//show errors, if any
if(errorsObject.fieldErrors)
{
StrutsUtils.showValidationErrors(form, errorsObject);
}
else
{
//good to go, regular submit
form.submit();
}
}
/* This is one of the functions that doesn't work using the simple theme, so I redefined it.
This can be changed to clear the previous errors, as it does in the commented example
cleaning the errors on divErrors.
As I am just showing the messages with alerts I don't need to clear anything,
but the method still need to be redefined, even if it is empty.
*/
StrutsUtils.clearValidationErrors = function(form, errors) {
//clear the div errors
//$('#divErrors').empty();
}
/* This method is responsible to show the messages.
The original versions works with the xhrml and css-xhtml theme but doesn't work with the simple theme
so I override the method with another implementation that shows the messages using alerts.
You can change the implementation to show the messages as you want,
but as the previous method this has to be redefined.
*/
StrutsUtils.showValidationErrors = function(form, errors) {
if(errors.fieldErrors)
{alert((errors.fieldErrors))
for(var fieldName in errors.fieldErrors)
{
alert("errors.fieldErrors[fieldName] " + errors.fieldErrors[fieldName]);
for(var i = 0; i < errors.fieldErrors[fieldName].length; i++)
{
alert('Field ->' + fieldName + '\nError -> ' + errors.fieldErrors[fieldName][i]);
}
}
}
};
but when i execute the code i get no organized JSON text i showed in alert message box, the field name is not like the one in the error message, the second field name is missing, the third field name is cut (i.e. carrierNo becomes rNo ).
can you help me. i want the field name in the JSON error match the error message text
I just figured out what is the problem, but i don't know why it happens and why.
it always remove the first 6 characters. why this happens
well I figured out the problem.
it was a but in org.apache.struts2.interceptor.validation.JSONValidationInterceptor
it removes the 6 first characters because of this incomplete if statement
sb.append((validationAware instanceof ModelDriven) ? ((String)fieldError.getKey()).substring(6) : (String)fieldError.getKey());
this error is fuond in struts 2.1.8
it should be like this
sb.append(((validationAware instanceof ModelDriven)) && (fieldErrorKey.startsWith("model.")) ? fieldErrorKey.substring(6) : fieldErrorKey);
it was corrected in later struts releses. i corrected the problem. and i thought i have to share the information for people who faces the problem.

Resources