Retrive ids and check related boxes - laravel-8

Using
Laravel 8.54
Livewire 2.6
Laratrust package for roles and permissions
I want to edit the permissions role like that
RolesEdit.php (livewire component)
<?php
namespace App\Http\Livewire\Admin\Roles;
use App\Models\Role;
use Livewire\Component;
use App\Models\Permission;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Validator;
class RolesEdit extends Component
{
public $data = [];
public $role;
public $selectedIds = [];
public function mount(Role $role)
{
$this->role = $role;
$this->data = $role->toArray();
}
public function update()
{
$this->data['permissions'] = $this->selectedIds;
$validated = Arr::except($this->validatedData(), ['permissions']);
$this->role->update($validated);
$this->role->permissions()->sync($this->data['permissions']);
}
public function validatedData()
{
return Validator::make($this->data, [
'display_name' => 'required',
'description' => 'required',
"permissions" => "required|array|min:1",
"permissions.*" => "required|distinct|min:1",
])->validate();
}
public function render()
{
$permissions = Permission::all();
return view('livewire.admin.roles.roles-edit', compact('permissions'));
}
}
Roles-edit.blade.php
<div class="mt-1">
<label class="form-label">{{ __('site.display_name') }}</label>
<input wire:model="data.display_name" type="text" class="form-control" placeholder="Enter role name" />
</div>
<div class="mt-1">
<label class="form-label">{{ __('site.role_description') }}</label>
<textarea wire:model="data.description" type="text" class="form-control"
placeholder="Enter Description"></textarea>
</div>
<div class="row w-100">
#foreach ($permissions as $permission)
<div class="col-md-3">
<div class="form-check ms-5">
<input wire:model.defer="selectedIds" class="form-check-input" id="{{ $permission->name }}"
value="{{ $permission->id }}" type="checkbox"
{{ $role->permissions->contains($permission->id) ? 'checked' : '' }} />
<label class="form-check-label" for="{{ $permission->name }}">
{{ $permission->display_name }}</label>
</div>
</div>
#endforeach
</div>
When I open roles-edit view I want to check boxes that have $permission->id related to role so I use
{{ $role->permissions->contains($permission->id) ? 'checked' : '' }}
But it did not work … all checkboxes is unchecked

instead using code:
{{ $role->permissions->contains($permission->id) ? 'checked' : '' }}
try this
#if($role->permissions->contains($permission->id)) checked #endif
also try to add wire:key directive to the parent div of the input element
<div class="form-check ms-5" wire:key="input-checkbox-{{ $permission->id }}">
I suggest you, create an array to retrieve the permissions ids of the role
public $permissionsIds = [];
public function mount(Role $role)
{
$this->role = $role;
$this->data = $role->toArray();
$this->permissionsIds = $this->role->permissions()->pluck('id');
}
// in blade
#if(in_array($permission->id,$permissionsIds)) checked #endif

Related

Laravel Livewire Real Time Validation switching between classes

I'm wondering about how I can switch between classes in Livewire real time form validation?
let's imagine that i have a form with some input fields such as (email) inside the input class I have a laravel directive #error('email') is-invalid #enderror this will repeat "is-invalid" class when the form field is empty.
what I want to achieve is switching between "is-invalid " and "is-valid" classes the first one if the form field is empty and second one if the form field is filled.
Here is my code :
class ContactForm extends Component
{
public $name;
public $email;
protected $rules = [
'name' => 'required|min:6',
'email' => 'required|email',
];
public function updated($propertyName)
{
$this->validateOnly($propertyName);
}
public function saveContact()
{
$validatedData = $this->validate();
Contact::create($validatedData);
}
}
<form wire:submit.prevent="saveContact">
<input type="text" wire:model="name" class="#error('name') is-invalid #enderror">
#error('name') <span class="error">{{ $message }}</span> #enderror
<input type="text" wire:model="email" class="#error('email') is-invalid #enderror">
#error('email') <span class="error">{{ $message }}</span> #enderror
<button type="submit">Save Contact</button>
</form>
We can use the error bag $errors and check if it has an error with the existing #error blade directive to show the error message.
<form wire:submit.prevent="saveContact">
<input type="text" wire:model="name" class="#if($errors->has('name')) is-invalid #else is-valid #endif">
#error('name') <span class="error">{{ $message }}</span> #enderror
<input type="text" wire:model="email" class="#if($errors->has('email')) is-invalid #else is-valid #endif">
#error('email') <span class="error">{{ $message }}</span> #enderror
<button type="submit">Save Contact</button>
</form>
I have used the has function from the error bag and the usual #if blade directive to achieve this.
Now if there is no error and input is valid, the is-valid class will be added.
Similarly if the validation fails, is-invalid class will be added.
jhones,
You need to address it with javascript. See my answer below.
class ContactForm extends Component
{
public $name;
public $email;
protected $rules = [
'name' => 'required|min:6',
'email' => 'required|email',
];
public function updated($propertyName)
{
$this->validateOnly($propertyName);
}
public function saveContact()
{
$validatedData = $this->validate();
Contact::create($validatedData);
}
}
<form wire:submit.prevent="saveContact">
<input type="text" wire:model="name" class="#error('name') is-invalid #else is-valid #enderror" id="name-input">
#error('name') <span class="error">{{ $message }}</span> #enderror
<input type="text" wire:model="email" class="#error('email') is-invalid #else is-valid #enderror" id="email-input">
#error('email') <span class="error">{{ $message }}</span> #enderror
<button type="submit">Save Contact</button>
</form>
<!-- javascript here: i use jquery syntaxe here -->
<script>
$(document).ready(function() {
$('#name-input').change(function(){
$(this).removeClass('is-invalid')
});
$('#email-input').change(function(){
$(this).removeClass('is-invalid')
});
})
</script>
Explanation 👇
I modify the HTML as following:
<input type="text" wire:model="name" class="#error('name') is-invalid #else is-valid #enderror" id="name-input">
#error('name') <span class="error">{{ $message }}</span> #enderror
<input type="text" wire:model="email" class="#error('email') is-invalid #else is-valid #enderror" id="email-input">
I add an id to each input to be able to call them in the script later.
Also i add the class "is-valid" if the server didn't return an error msg.
Hope this solution helps you. Let me know
Hi friend you can use ;
<input id="email" class="form-control #if($errors->has('form.email')) is-invalid #else {{ $is_valid }} #endif" name="email" type="email" wire:model.lazy="form.email">
#error('form.email')<label id="email-error" class="error invalid-feedback" for="email" >{{ $message }}</label> #enderror
And class is ;
public function updated($name)
{
$a= $this->validateOnly($name, [
'form.email' => 'required|email',
'form.password' => 'required',
]);
if($a) {
$this->is_valid='is-valid';
}
else {
$this->is_valid='';
}
}

In my creation process I want to write to another entity than only the used

If I submit the page the first save goes without a problem
Than I assigned all values to the other entity which I want to write to create there a new record.
Why do I get an System Null Reference. I have in all fields the values which I want?
[
=== here is my c# Code ===========
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using WorkCollaboration.Data;
using WorkCollaboration.Models;
namespace WorkCollaboration.Pages.TimeReports
{
public class CreateModel : PageModel
{
private readonly WorkCollaboration.Data.WorkCollaborationContext _context;
public CreateModel(WorkCollaboration.Data.WorkCollaborationContext context)
{
_context = context;
}
public IActionResult OnGet()
{
CusContactDropDownDisp = _context.CusContactDropDown.ToList(); // Added for DropDown
SupContactDropDownDisp = _context.SupContactDropDown.ToList(); // Added for DropDown
return Page();
}
[BindProperty]
public TimeReport TimeReport { get; set; }
public IEnumerable<Models.CusContactDropDown> CusContactDropDownDisp { get; set; }
public IEnumerable<Models.SupContactDropDown> SupContactDropDownDisp { get; set; }
public Models.PointsforSupContact PointsforSupContact { get; set; }
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see https://aka.ms/RazorPagesCRUD.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
TimeReport.TimeReportSupContactPointValue = (TimeReport.TimeReportHours * 10);
_context.TimeReport.Add(TimeReport);
await _context.SaveChangesAsync();
//============================================
// Adding new Point Record to Supplier Contact
//============================================
PointsforSupContact.PointsId = TimeReport.TimeReportId;
PointsforSupContact.PointsSupContactId = TimeReport.TimeReportSupplierTalentContactId;
PointsforSupContact.PointsInternalUserId = 1; // User 1 Christof Oberholzer must be entered in Contacts and User
PointsforSupContact.PointsDate = TimeReport.TimeReportDate;
PointsforSupContact.PointsTotal = TimeReport.TimeReportSupContactPointValue;
PointsforSupContact.PointsText = TimeReport.TimeReportText;
PointsforSupContact.PointsTitle = "TimeReporting Points";
_context.PointsforSupContact.Add(PointsforSupContact);
await _context.SaveChangesAsync();
return RedirectToPage("/TimeReportOverview/Index");
}
}
}
==== My Page ======
#page
#using Microsoft.AspNetCore.Localization
#using Microsoft.AspNetCore.Mvc.Localization
#model WorkCollaboration.Pages.TimeReports.CreateModel
#{
ViewData["Title"] = "Create";
ViewData["RandomId"] = Guid.NewGuid().GetHashCode();
}
#inject IViewLocalizer Localizer
<h1>Create</h1>
<h4>TimeReport</h4>
<p>
<a asp-page="/TimeReportOverview/Index">Back to Index</a>
</p>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="TimeReport.TimeReportSupContactPointValue" value="0"/>
<div class="form-group">
<label asp-for="TimeReport.TimeReportId" class="control-label"></label>
<input asp-for="TimeReport.TimeReportId" value='#ViewData["RandomId"]' readonly="readonly" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TimeReport.TimeReportCustomerNeedContactId" class="control-label"></label>
</div>
<select id="CusContactId" asp-for="CusContactDropDownDisp" asp-items="#(new SelectList(Model.CusContactDropDownDisp,"CusContactId","CusFullName"))">
<option value="" selected disabled>--Choose Customer--</option>
</select>
<div class="form-group">
<input asp-for="TimeReport.TimeReportCustomerNeedContactId" readonly="readonly" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportCustomerNeedContactId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TimeReport.TimeReportSupplierTalentContactId" class="control-label"></label>
</div>
<select id="SupContactId" asp-for="SupContactDropDownDisp" asp-items="#(new SelectList(Model.SupContactDropDownDisp,"SupContactId","SupFullName"))">
<option value="" selected disabled>--Choose Supplier--</option>
</select>
<div class="form-group">
<input asp-for="TimeReport.TimeReportSupplierTalentContactId" readonly="readonly" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportSupplierTalentContactId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TimeReport.TimeReportDate" class="control-label"></label>
<input type="datetime-local" asp-for="TimeReport.TimeReportDate" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TimeReport.TimeReportHours" class="control-label"></label>
<input asp-for="TimeReport.TimeReportHours" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportHours" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TimeReport.TimeReportText" class="control-label"></label>
<input asp-for="TimeReport.TimeReportText" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportText" class="text-danger"></span>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TimeReport.TimeReportState, htmlAttributes: new { #class = "form-group" })
<div class="form-group">
#Html.DropDownListFor(model => model.TimeReport.TimeReportState, new List<SelectListItem>
{
new SelectListItem {Text = "Gebucht", Value = "Reported", Selected = true },
new SelectListItem {Text = "Kontrolliert", Value = "Controlled" },
new SelectListItem {Text = "Verrechnet / Noch nicht bezahlt", Value = "Invoiced / Not yet payed" },
new SelectListItem {Text = "Verrechnet / Bezahlt", Value = "Invoiced / Payed" },
}, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.TimeReport.TimeReportState, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
Back to List
</div>
</form>
</div>
</div>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
<script>
$("#CusContactId").on("change", function () {
$("#TimeReport_TimeReportCustomerNeedContactId").val($("#CusContactId").val());
});
$("#SupContactId").on("change", function () {
$("#TimeReport_TimeReportSupplierTalentContactId").val($("#SupContactId").val());
});
</script>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Thank you for your help
First In your view:
ViewData["RandomId"] = Guid.NewGuid().GetHashCode();
GetHashCodemethod make the Guid to int,please make sure it matches the type in your model.
Then the right way to add new PointsforSupContact is to create a new PointsforSupContact,so you need to delete the code:
public Models.PointsforSupContact PointsforSupContact { get; set; }
and change you code to:
//...
await _context.SaveChangesAsync();
//add this line
var PointsforSupContact=new PointsforSupContact();
PointsforSupContact.PointsId = TimeReport.TimeReportId;
//...

Trying to get property of non-object (View: C:\xampp\htdocs\MyP\resources\views\pekerja\index.blade.php)

i have problem 'Trying to get property of non-object' on this code. please someone check this code for make me clear. TQ
index.blade.php
<div class="form-group">
<label for="idUnit" class="control-label col-sm-3">Unit :</label>
<div class="col-sm-9">
<select name="idUnit" class="form-control input-sm" id="idUnit" disabled="disabled">
<option value="">Sila Pilih...</option> ---> error on this code!
#foreach ($KodUnit as $unit)
<option value="{{ $unit->id }}"
#if(isset(request()->idUnit) && request()->idUnit == $unit->id)
selected="selected"
#endif
>{{ $unit->nama }}</option>
#endforeach
</select>
</div>
</div>```
kodUnit model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class KodUnit extends Model
{
protected $table = 'kod_unit';
protected $primaryKey = 'id';
protected $fillable = ['id', 'kod', 'nama'];
public $timestamps = false;
}

How to save category in laravel 5.7 with vue.js

Using Laravel 5.7 with vuejs, I am trying to display parent_id from a MySQL categories table. I want to pass the name and get all it's child categories irrespective of the parent.
My blade
<form action="{{ route('categories.store') }}" method="post">
#csrf
<div class="form-group">
<label for="name">name:</label>
<input type="text" id="name" class="form-control" v-model="name">
</div>
<div class="form-group">
<label for="sub_category">category</label>
<select id="sub_category" v-model="parent_id" class="form-control">
<option data-display="main category" value="0">main category</option>
<option v-for="category in categories" :value="category.id">#{{ category.name }}</option>
</select>
</div>
<div class="form-group">
<button type="button" #click="addCategory()" class="btn btn-info">save</button>
</div>
</form>
web.php
Route::group(['namespace' => 'Admin', 'prefix' => 'admin'],function (){
$this->get('panel', 'PanelController#index')->name('panel.index');
$this->resource('categories', 'CategoryController');
});
My vue
addCategory: function () {
axios.post(route('categories.store'), {
name: this.name,
parent_id: this.parent_id,
}).then(response => {
this.categories.push({'name': response.data.name, 'id': response.data.id});
}, response => {
this.error = 1;
console.log('Errors');
});
}
CategoryController
public function store(Request $request)
{
$category = new Category();
$category->name = $request->name;
$category->parent_id = $request->parent_id;
if ($category->save()) {
return $category;
}
}
I see this error in console for first
Too
And I get 405 error.
Remove #click from submit buttom.
Remove route... from form action and set it #
Add #submit="addCategory()" to the form
In the axios.post samply add the route without route function.
Update:
If you want to prevent page refreshing, add .prevent after #submit.

Aurelia custom element access data from child to parent view model

I am new to Aurelia and need help accessing values from custom element in another view.
I have a scenario where I would like to share input file for attachment in multiple forms. One of the approach I am taking is to create custom element for input files that can be shared with multiple forms in web application.
Below is my code:
Custom element called FilePicker which will be shared between multiple forms. In my Request paged I inserted the custom element called:
<file-picker router.bind="router" accept="image/*" multiple="true" ></file-picker>
My requirement is to access property called validFiles which is an array. I would like to use values from validFiles to custom object in Request view model called formData['attachment']
TS:
import { customElement, useView, bindable, bindingMode } from 'aurelia-framework';
#customElement('file-picker')
#useView('./file-picker.html')
export class FilePicker {
#bindable accept = '';
#bindable multiple = false;
#bindable({ defaultBindingMode: bindingMode.twoWay }) files: FileList;
validFiles = [];
input: HTMLInputElement;
// Validate function for on change event to input file.
public filesChanged() {
if (!this.files) {
this.clearSelection();
}
if (this.files) {
this.processFiles();
}
}
// Trigger on button click
public triggerInputClick() {
this.input.click();
}
// Find value in array of object
private findValinArrObj(arr, key, val) {
return arr.map(function (v) { return v[key] }).indexOf(val);
}
// Process file for each new files uploaded via browser
private processFiles() {
if (this.files) {
for (let i = 0; i < this.files.length; i++) {
let findFile = this.findValinArrObj(this.validFiles, 'name', this.files.item(i).name);
if (findFile === -1) {
this.validFiles.push(this.files.item(i));
}
}
this.clearSelection();
}
}
// Remove file from fileNames and validFiles array
public removeByFileName(fileName) {
if (this.validFiles) {
for (let i = 0; i < this.validFiles.length; i++) {
if (this.validFiles[i].name === fileName) {
this.validFiles.splice(i, 1);
}
}
}
}
// Clear input file in DOM
private clearSelection() {
this.input.type = '';
this.input.type = 'file';
}
}
HTML:
<template>
<input type="file" accept.bind="accept" multiple.bind="multiple"
files.bind="files" ref="input"
style="visibility: hidden; width: 0; height: 0;">
<button class="btn btn-primary" click.delegate="triggerInputClick()">
<slot>Browse...</slot>
</button>
<ul class="list-group" if.bind="validFiles">
<li class="list-group-item" repeat.for="file of validFiles" style="padding: 0; border:none;">
${file.name} <span class="glyphicon glyphicon-remove text-danger" style="cursor: pointer;" click.delegate="removeByFileName(file.name)"></span>
</li>
</ul>
</template>
Parent View Model:
TS:
export class Request {
pageTitle: string = "Request Page";
title: string = '';
description: string = '';
businessValue: string = '';
emails: string = '';
formData: object = {};
public postData() {
this.formData['title'] = this.title;
this.formData['description'] = this.description;
this.formData['businessValue'] = this.businessValue;
this.formData['emails'] = this.emails;
this.formData['attachment'] = [];
console.log(this.formData);
}
}
HTML:
<template>
<require from="./request.css"></require>
<require from="../../resources/elements/file-picker"></require>
<div class="panel panel-primary">
<div class="panel-heading">${pageTitle}</div>
<div class="panel-body">
<form class="form-horizontal">
<div class="form-group">
<label for="title" class="col-sm-2 control-label">Title</label>
<div class="col-sm-10">
<input type="text" value.two-way="title" class="form-control" id="title" placeholder="Brief one-line summary of the request">
</div>
</div>
<div class="form-group">
<label for="description" class="col-sm-2 control-label">Description</label>
<div class="col-sm-10">
<input type="text" value.two-way="description" class="form-control" id="description" placeholder="Detailed description of the request">
</div>
</div>
<div class="form-group">
<label for="description" class="col-sm-2 control-label">Business Value</label>
<div class="col-sm-10">
<input type="text" value.two-way="businessValue" class="form-control" id="description" placeholder="Description of how this offers business value">
</div>
</div>
<div class="form-group">
<label for="emails" class="col-sm-2 control-label">Email</label>
<div class="col-sm-10">
<input type="text" value.two-way="emails" class="form-control" id="emails" placeholder="Provide email address">
</div>
</div>
<div class="form-group">
<label for="exampleInputFile" class="col-sm-2 control-label">Attachment(s)</label>
<div class="col-sm-10">
<file-picker router.bind="router" accept="image/*" multiple="true" ></file-picker>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="submit" class="btn btn-default pull-right" click.trigger="postData()">Submit</button>
</div>
</div>
</form>
</div>
</div>
</template>
Any help is really appreciated. :)
You can set up two-way-binding on your Request view, to bind the validFiles in your child view (file-picker) to a variable in your parent view (Request):
request.html:
<file-picker valid-files.two-way="validFiles"></file-picker>
request.ts:
public validFiles: File[];
file-picker.ts:
#bindable
public validFiles: File[];
This way any changes made to the validFiles object in either the child or the parent will update the object in both viewmodels.