Problem is, everytime I try to save the file, the validation triggers saying that the image is required. I did dd($rental->images) (before the save method) and sure enough, it returns empty:
Yeah I did. What’s weird is without the validation, it saves fine. But with the validation, it does not. I had to create a custom validation in my php code field for it to work, but this may be a bug.
I don’t have a model class since I’m using Tailor’s built in functions to create the data. The validation rules are here:
uuid: 10b46eed-a314-11ed-adae-4836e528207e
handle: Rentals\Rentals
type: stream
name: Rentals
drafts: true
multisite: sync
primaryNavigation:
icon: icon-home
order: 140
navigation:
parent: Rentals\Rentals
icon: icon-home
order: 140
customMessages:
buttonCreate: New Rental
fields:
slug:
validation:
- required
- unique:xc_10b46eeda31411edadae4836e528207ec,slug
content:
type: richeditor
span: adaptive
label: Property Description
tab: Description
column: false
validation: required
location:
type: entries
source: Rentals\Locations
label: General Location
tab: Location
commentAbove: Select the general location of your rental property. Used for the rental search and throughout the site
span: left
column: false
validation: required_if:show_map,true
address:
label: Address
type: addressfinder
commentAbove: Add the address of the Rental Location
tab: Location
span: right
validation: required
column:
label: Address
type: Text
show_map:
label: Show Map
comment: Show the map for this rental
span: right
tab: Location
type: switch
column: false
scope: false
hr_location:
type: ruler
tab: Location
trigger:
action: show
field: show_map
condition: checked
general_location:
label: General Location
type: addressfinder
commentAbove: Choose a location that is close to the rental. Used for the map fields below. You can also set the Latitude & Longitude Directly
tab: Location
span: left
column: false
validation: required_if:show_map,true
trigger:
action: show
field: show_map
condition: checked
fieldMap:
latitude: latitude
longitude: longitude
map_zoom_level:
label: Map Zoom Level
type: number
min: 0
max: 18
default: 12
tab: Location
span: right
column: false
commentAbove: Choose the zoom level of the map on the page
trigger:
action: show
field: show_map
condition: checked
latitude:
type: text
label: Latitude
tab: Location
span: left
column: false
validation: required_if:show_map,true
trigger:
action: show
field: show_map
condition: checked
longitude:
type: text
label: Longitude
tab: Location
span: right
column: false
validation: required_if:show_map,true
trigger:
action: show
field: show_map
condition: checked
location_info:
type: richeditor
label: Location Information
commentAbove: Add information about this location. Appears right after the map.
tab: Location
column: false
ical_url:
label: iCal URL
commentAbove: The link to the bookings related to this rental. Used to block off other calendars (Airbnb, VRBO, etc)
type: partial
path: "#/adeluxurystay/partials/fields/_ical_url"
tab: Rental Info
max_guests:
type: number
label: Max No. of Guests
commentAbove: The Max number of guests for this rental
tab: Rental Info
span: left
column: false
validation:
- "required"
minimum_stay:
type: number
label: Minimum Stay
span: right
tab: Rental Info
commentAbove: The minimum number of days the person can book.
column: false
validation:
- required
booking_buffer:
type: number
label: Booking Buffer
span: left
tab: Rental Info
commentAbove: The minimum number of days the person can book from today. Set to 0 for same day booking.
column: false
validation:
- required
featured:
type: switch
label: Featured
comment: Feature this rental property throughout the site.
tab: Rental Info
span: right
cssClass: mt-0 mt-lg-5
hr_1:
type: ruler
tab: Rental Info
images:
type: fileupload
validation: required
mode: image
label: Images
commentAbove: Images for this rental property. The first image is used as the main image
tab: Rental Info
scope: false
column:
label: Images
type: image
sortable: true
hr_2:
type: ruler
tab: Rental Info
beds:
type: number
label: No. of Beds
commentAbove: The number of beds in this rental
tab: Rental Info
span: row
spanClass: col-12 col-lg-4
validation: required
bedrooms:
type: number
label: No. of Bedrooms
commentAbove: The number of bedrooms in this rental
tab: Rental Info
span: row
spanClass: col-12 col-lg-4
validation: required
bath:
type: number
label: No. of Bath
commentAbove: The number of baths in this rental
tab: Rental Info
span: row
spanClass: col-12 col-lg-4
validation: required
hr_3:
type: ruler
tab: Rental Info
amenities:
type: entries
label: Amenities
source: Rentals\Amenities
commentAbove: Available amenities for this rental property.
tab: Rental Info
span: left
quickselect: true
column: false
scope: false
house_rules:
type: entries
label: House Rules
source: Rentals\HouseRules
commentAbove: Add House Rules to this rental property.
tab: Rental Info
span: right
quickselect: true
column: false
scope: false
check_in_instructions:
type: richeditor
label: Check In Instructions
commentAbove: Add specific check in instructions for this rental
tab: Rental Info
column: false
validation: required
email_header:
type: richeditor
label: Email Header
commentAbove: Add content to the beginning of the email when the guests' booking is complete.
tab: Rental Info
span: left
column: false
validation: required
email_footer:
type: richeditor
label: Email Footer
commentAbove: Add content to the end of the email when the guests' booking is complete.
tab: Rental Info
span: right
column: false
validation: required
price:
type: number
label: Price
commentAbove: The default price per night for this rental unit
span: left
tab: Pricing & Options
validation: required
column:
label: Price
type: number
format: "$%.2f"
price_per_extra_guest:
type: number
label: Price per Extra Guest
commentAbove: Add a fee on top of the default price per extra guests.
span: right
tab: Pricing & Options
column:
label: Price per Extra Guest
type: number
format: "$%.2f"
deposit:
label: Deposit (Incidental Fee)
type: number
tab: Pricing & Options
commentAbove: Hold an amount on the the customer's card. Amount refunded is determined by the booking settings. Used when the user books. If not set, Defaults to the Global Deposit.
span: left
valdiation: required
services:
type: entries
label: Services
commentAbove: Associated services for this rental that the customer can add.
displayMode: taglist
inverse: rentals
source: Rentals\Services
tab: Pricing & Options
hidden: false
span: right
hr_4:
tab: Pricing & Options
type: ruler
fees:
type: repeater
label: Fees
commentAbove: The fees associated with this rental
tab: Pricing & Options
span: left
column: false
form:
fields:
name:
type: text
label: Fee Name
span: row
spanClass: col-12 col-lg-4
price:
type: number
label: Price
span: row
spanClass: col-12 col-lg-4
pricing_style:
type: dropdown
label: Pricing Style
span: row
spanClass: col-12 col-lg-4
options:
fixed: Fixed
percent: Percent
availability:
type: repeater
label: Availability
tab: Pricing & Options
commentAbove: Add specific Pricing per day.
prompt: Add Availability
span: right
readOnly: true
form:
fields:
check_in:
type: datepicker
mode: date
format: M d, Y
useTimezone: true
label: Check In
span: left
default: today
readOnly: true
check_out:
type: datepicker
mode: date
format: M d, Y
useTimezone: true
label: Check Out
span: right
default: today
readOnly: true
available:
type: switch
label: Available?
span: left
comment: Whether or not this rental is available at the above time
cssClass: mt-0 mt-lg-4
default: 1
readOnly: true
price:
type: number
label: Price
span: right
readOnly: true
trigger:
action: show
condition: checked
field: available
cancellation:
type: switch
label: Allow Cancellation?
comment: Allow cancellation for this rental
tab: Cancellation & Updates
span: left
default: true
column: false
scope:
label: Cancellable
free_24_hour_cancellation:
type: switch
label: Free 24 Hour Cancellation
comment: Disable fees if the customer cancels the booking within 24 Hours.
tab: Cancellation & Updates
span: right
default: true
column: false
trigger:
action: show
field: cancellation
condition: checked
scope:
label: 24hr Hour Cancellation
cancellation_fees:
type: repeater
tab: Cancellation & Updates
label: Cancellation fees
commentAbove: Apply fees based on when the booking is cancelled.
column: false
form:
fields:
days:
type: number
label: Days
comment: Number of days before the check in date where the cancellation incurs a fee.
span: row
spanClass: col-12 col-lg-4
price:
type: number
label: Price
span: row
spanClass: col-12 col-lg-4
pricing_style:
type: dropdown
label: Pricing Style
span: row
spanClass: col-12 col-lg-4
options:
fixed: Fixed
percent: Percent
trigger:
action: show
condition: checked
field: cancellation
stay_reduction_fees:
type: repeater
tab: Cancellation & Updates
label: Stay Reduction Fees
commentAbove: Apply fees based on when the booking stay length is reduced.
column: false
form:
fields:
days:
type: number
label: Days
comment: Number days before their check in date where their stay reduction incurs a fee.
span: row
spanClass: col-12 col-lg-4
price:
type: number
label: Price
span: row
spanClass: col-12 col-lg-4
pricing_style:
type: dropdown
label: Pricing Style
span: row
spanClass: col-12 col-lg-4
options:
fixed: Fixed
percent: Percent
cancellation_form:
label: Cancellation Form
commentAbove: This form will be used if the user wishes to cancel. Leave empty to use the global cancellation form
type: entries
source: Content\Forms
tab: Cancellation & Updates
maxItems: 1
displayMode: recordfinder
span: left
title: Find Form
column: false
scope: false
check_in_date_buffer:
label: Check-in Date Buffer
commentAbove: Choose the amount of days before the check-in date that they can change the check-in date.
type: number
column: false
scope: false
tab: Cancellation & Updates
span: right
default: 1
ical_urls:
type: repeater
commentAbove: Add iCal URLS to your rental to block off previously booked time from other platforms
label: iCal URLs
tab: Calendar Sync
column: false
form:
fields:
name:
label: Name
type: text
tab: Calendar Sync
span: left
commentAbove: The name of the iCal URL. Used for the Backend Dashboard.
ical_url:
type: text
label: iCal URL
tab: Calendar Sync
commentAbove: Enter your iCal URL to Check availability against other platforms and apply them here.
span: right
column: false
color:
type: colorpicker
label: Color
commentAbove: Choose a color for this event. Used for the Backend Dashboard.
bookings:
type: entries
label: Bookings
commentAbove: Associated bookings for this rental
inverse: rental
source: Bookings\Bookings
tab: Bookings
hidden: true
column: false
scope: false
owner_type:
type: dropdown
label: Owner Type
commentAbove: Specify the owner type of the rental. Used for rental administrative tasks.
tab: Manage
span: left
options:
user: User (From User Plugin)
admin: Admin (From Backend)
user_owner:
label: Owner
type: recordfinder
list: ~/plugins/rainlab/user/models/user/columns.yaml
recordsPerPage: 10
title: Find User
tab: Manage
descriptionFrom: email
useRelation: false
modelClass: RainLab\User\Models\User
disabled: false
span: right
commentAbove: The owner of this rental.
conditions: rental_owner = 1
validation: required_if:owner_type,user
column:
label: User
type: partial
path: "#/adeluxurystay/partials/columns/_user"
trigger:
action: show
condition: value[user]
field: owner_type
admin_owner:
label: Owner
type: recordfinder
list: ~/modules/backend/models/user/columns.yaml
recordsPerPage: 10
title: Find User
tab: Manage
nameFrom: first_name
descriptionFrom: email
useRelation: false
modelClass: Backend\Models\User
disabled: false
span: right
commentAbove: The owner of this rental.
conditions: is_activated = true
validation: required_if:owner_type,admin
column:
label: User
type: partial
path: "#/adeluxurystay/partials/columns/_user"
trigger:
action: show
condition: value[admin]
field: owner_type
booking_email_recipient:
label: Booking Email Recipient
commentAbove: Specify an email to send the admin emails. Leave empty to use the rental owner's email.
type: text
tab: Admin Emails
span: row
spanClass: col-12 col-lg-6
validation:
- email
booking_email_recipient_name:
label: Booking Email Recipient's Name
commentAbove: Specify an name to send the admin emails. Leave empty to use the rental owner's email.
type: text
tab: Admin Emails
span: row
spanClass: col-12 col-lg-6
validation: required_with:booking_email_recipient
booking_email_recipient_phone:
label: Booking Email Recipient's Phone
commentAbove: Specify a phone number for rental emails. Used for support. Leave empty to use the rental owner's email.
type: text
tab: Admin Emails
span: row
spanClass: col-12 col-lg-6
validation: required_with:booking_email_recipient
seo_fields:
tab: SEO
type: mixin
name: SEO Fields
source: Content\SEOFields
code_fields:
tab: SEO
type: mixin
name: SEO Fields
source: Content\CodeFields
1st:
probably, when you tried creating this “booking” from backend, everything works fine, right?
2nd:
you tried to create programatically new item, then, before you call $newModel->save() you need to attach that image, not after that. then only one change here is needed.
// creating a file reference
$file = new System\Models\File;
$file = $file->fromPost(Input::file('files')); // insert your input name for that field
$file->save();
// Attach the uploaded file to your model
$model = new EntryRecord::inSection('Rentals\Rentals');
$model->file()->add($file);
$model->save();
if (!empty(files('images'))) {
foreach (files('images') as $image) {
$file = new System\Models\File;
$file = $file->fromPost($image);
$file->save(); /// <<< here you create a $file
$rental->images->add($image); //// <<<< here you try to attach $image!
}
}
only one thing what i removed was that validation: required …
probably, there are issue with checking, because it is not “real field” but attachment, then validation just must be replaced with requried option.
allow user in backend to have that red dot as “required” (without validation)
allow users to upload and process images without that validation.
currently i think, this may be a good thing to raise an issue in tailor, when is created attach relations, to rewamp validation on attachment, instead of input field. @daft