InfyOmLabs / laravel-generator

API and Admin Panel CRUD Generator for Laravel.
https://www.infyom.com/open-source
MIT License
3.79k stars 812 forks source link

Many Issues #226

Closed baylf2000 closed 5 years ago

baylf2000 commented 8 years ago

Firstly thank you so much for your wonderful software.

I'm having a lot of problems when attempting to generate scaffolding for anything that contains any type of field other than plain strings or numbers. I've tried all kinds of versions, both the boilerplates and installing into a fresh Laravel 5.2 install as per the instructions on your website.

Are date and boolean field types supposed to be working at this point in time, because they really are not.

For example, when creating a scaffold for a model that includes a date, the scaffolding is created, and allows me to create a record which includes a date. This record is then correctly displayed in the index, but when I attempt to edit this record, the existing date information is not placed into the date field. It just shows "dd/mm/yyyy" again.

If I include a boolean field with a checkbox, there is no display of that field in the index, and when editing the record, the box is show, but it's always checked, no matter what the existing record is. If I save the record with the box unchecked, then I can see by looking at the database directly that the record is not changed.

I'd appreciate knowing if these are know issues, so that I can stop trying to solve problems that I'm not creating.

Thank you so much for your help.

phillipmadsen commented 8 years ago

Let me see if I can help.

I will look through the stub files and double check the stub file paths. As for the boolean with checkbox I pushed the updated files a while back but only half of them look like they are there so I will add them again.

Can you tell me what version of the repo you are using.

baylf2000 commented 8 years ago

Hi there,

I have tried using "dev-master" and "dev-develop" in composer.json, as well as the 5.2 branches of the bootstrap and adminlte boilerplates.

Thanks so much for your help.

baylf2000 commented 8 years ago

Regarding the issue with the date type, it looks the server is actually returning the correct date, but that the format doesn't match the one that the date field is expecting.

Please see screen capture attached for an example of a newly opened edit screen.

infyom_capture

baylf2000 commented 8 years ago

I can confirm that this is related to the date format of the HTML5 datepicker. The edit form works correctly with dates in Firefox, as the datepicker element does not seem to function at all in that browser.

The form does not work in Chrome or Microsoft Edge, where the datepicker does work. The datepicker requires two completely different date formats in those two browsers, neither of which matches the incoming format from Laravel. Chrome requires the local format "dd/mm/yyyy", while Edge requires "mm/dd/yyyy", despite them being installed on the same machine. The date from Laravel is in "yyyy-mm-dd" format.

Since the HTML5 version doesn't work at all in Firefox, and is buggy at best in other browsers, maybe it would be better to use another datepicker for the time being, where you can set the format it expects to match the format being delivered by Laravel?

Thanks again for all your help.

phillipmadsen commented 8 years ago

The date format is up to you in the bootstrap template the only one being used is the bootstrap one and it works fine in all browsers for me. As for the version to use I would use the master branch if you do now want to dig into the functionality of the package and adjust the needed code to suite your needs which would be what the dev branch is for at the moment. I have testing all the fields on a fresh install and it works fine for me in the big browsers. I guess my question would be have you tried setting the date format manually?

Something along the lines of these ones I use:

    /**
     * @param $date
     */
    public function getDateAttribute($value)
    {
        return Carbon::parse($value)->format('d/m/Y');
    }
    /**
     * @param $date
     */
    public function setDateAttribute($value)
    {
        $this->attributes['dob'] = Carbon::createFromFormat('d/m/Y', $value)->toDateString();
    }

    public function getPublishedAtAttribute($published_at)
    {
        return $this->attributes['publish_at'] = Carbon::parse($publish_at)->format('Y-m-d');
    }
      /**
     * @param $date
     */
    public function setAddedDateAttribute($date){

        $this->attributes['created_at'] = Carbon::createFromFormat('d-m-Y', $date);
    }

    /**
     * @param $date
     */
    public function setPublishedDateAttribute($date){

        $this->attributes['published_date'] = Carbon::toFormattedDateString('d-m-Y', $date);
    }

can I see your crud output by chance do you have a repo with it? or can you show me your edit.blade.php

baylf2000 commented 8 years ago

As I said originally, I have tried multiple original versions of laravel-generator on fresh installs of Laravel 5.2, as well as downloading your bootstrap boilerplate, and the issues I'm having are the same.

  1. When editing a model with a date, the original date does not show in the datepicker.
  2. When editing a boolean checkbox, the changes are not saved. The checkbox is always checked.

The HTML5 date picker is known to be broken in many browsers. Even if it does work, of particular concern is the inability to set the date format. It's set automatically from the browser's language. This means that you would somehow have to get the date format that a user's browser is using, and then tell Laravel to expect/return dates in that format.

I've changed my copy of the template to use bootstrap-datepicker. It's light, simple to use, widely compatible and it's easy to set the required date format to match whichever one is used in Laravel.

http://eternicode.github.io/bootstrap-datepicker/

Apart from the date issue, the bool-checkbox is also broken. It appears in the edit form, but it does not save. It's always either checked or unchecked.

phillipmadsen commented 8 years ago

I need to see your code to help you further. Not sure if you tried this option or not but you can always add the old attribute to your field. Here is an example of one I used in the past.

{!! Form::file('product_name', null, ['class'=>'form-control', 'id' => 'product_name', 'value'=>Input::old('product_name')]) !!}
baylf2000 commented 8 years ago

While I really do appreciate your efforts, I don't know what else I can do to explain the issues. I'm not sure you're understanding.

Your standard code generates broken output when it comes to both date fields and checkboxes.

Datepicker You are using the HTML5 datepicker in your code for your date fields which will never work properly for all international users the way you are using it.

  1. By default, when you edit a record, Laravel returns the date field from the database in whatever format has been set for the whatever database Laravel is using, for example "YYYY-MM-DD".
  2. the HTML5 datepicker will check that returned date field to see that it matches the format it is configured for, based on the user's browser settings. For example, in my Chrome browser (in Australia) it's "DD/MM/YYYY" and you CANNOT change that expectation in code.
  3. If the format from Laravel does not match the format that the HTML5 datepicker is expecting (as it does not in the above case), then the datepicker will reject that input and leave browser date box blank. You can see this in the error message in the browser console.
  4. Yes, I could use a Laravel mutator in the model to alter the date format returned by Laravel to match the one I know my browser expects, but what about the next user? What if they are from the US and their HTML5 datepicker expects a different format again, like"MM/DD/YYYY"? Then the whole thing will be broken all over again.
  5. Therefore I can't see how you can ever be certain that the database format, laravel format and browser format will match. And they MUST match if the HTML5 datepicker is ever to work and be populated from the database.

I don't know how much clearer than that I can be. You don't need to see any code from me. My code won't show you the issue. The issue only shows up in the browser.

My solution has been to implement the datepicker I listed above. Then I can control the format that the datepicker expects, and returns, by code, and match it to whatever I set in the database and/or Laravel.

Checkbox In relation to the boolean checkbox option, your code is seems to be incomplete. Laravel does not seem to offer this functionality automatically. You need to parse the output from the browser form and convert it to a boolean value to be stored in the database, and then do the reverse when displaying the database value in a checkbox.

The checkbox only returns a value to Laravel if it's checked. If it's not, the field is missing entirely from the fields and values returned to Laravel. You can overcome this by adding a hidden field with the same name BEFORE the checkbox. If the checkbox is not checked, the hidden field and value will be returned. If the checkbox is checked, it will override the hidden field with its own value. For example, for a checkbox named "approved": (note: I'm relatively new to php and Laravel, so please excuse my code)

<!-- Boolean Checkbox -->
<div class="form-group col-sm-2 checkbox checkbox-inline">
    <label>
        {{ Form::hidden('approved', 0) }}
        @if ($application->approved)
            {{ Form::checkbox('approved', 1, true) }}
        @else
            {{ Form::checkbox('approved', 1, false) }}
        @endif
        Active
    </label>
</div>

You can then add a Laravel mutator in your model to convert "1" and "0" to numeric(boolean) 1 and 0 to be stored in the database.

public function setApprovedAttribute($value)  
{  
    if ($value === '1') {  
        $this->attributes['approved'] = 1;  
    } elseif ($value === 'false') {  
        $this->attributes['approved'] = 0;  
    }  
}

Also, you'll need a Laravel accessor in the model to ensure a value of either 1 or 0 is always returned.

public function getApprovedAttribute($value)
{
    if($value === 1)
    {
        return 1;
    } else {
        return 0;
    }
}

Finally, you might want to add some other custom method to use when displaying the boolean value from the database in the index view (or just some Blade code would also work) so that rather than just "1" or "0" you get a "yes" or "no" or "true" or "false" or something else that makes sense, like a font-awesome tick or cross.

I hope this all makes some sense. I appreciate your time and effort.

ObaidParacha commented 8 years ago

type="datetime-local" will work, gives picker in chrome for date only, gives picker edge(windows 10 explorer) for both date and time. and firefox didn't give me any :( and the formatting is yyyy-mm-dd HH:MM:SS

type="datetime"also works but it don't show date-picker in all browsers simple type="date" simply doesn't work because of opposite formatting.

firefox don't like me :(

@baylf2000 i thnk type="datetime" will solve your issue, no ? as datetime-local is the one which uses their browser formatting ?

baylf2000 commented 8 years ago

Hi @mastermind23. Thanks so much for your suggestions.

No, I'm afraid all of the HTML5 date types use the format of the local browser. type="datetime" has been removed completely from the HTML spec, as so will soon no longer work in any browser.

Apart from that, a solution that is broken for 50% of users is not really a solution, and I think most developers would agree that those HTML5 features are very poorly implemented even in the browsers which do support them, and so should not be used.

At this stage I'll stick with the simple, lightweight and reliable solution I mentioned above.

Hope this helps.

phillipmadsen commented 8 years ago

Here is one thing I see that you will need to adjust. jsut fyi your if and else are returning the same value of true 1. the else should be 0, false but that is the same as using {{ Form::checkbox('approved) }}

<!-- Boolean Checkbox -->
<div class="form-group col-sm-2 checkbox checkbox-inline">
    <label>
        {{ Form::hidden('approved', 0) }}
        @if ($application->approved)
            {{ Form::checkbox('approved', 1, true) }}
        @else
            {{ Form::checkbox('approved', 1, false) }}
        @endif
        Active
    </label>
</div>

The boolean checkbox does not return values it returns either 0 for false or 1 for true. if you need values you need to use the normal checkbox.

Also there is not hidden field you should remove it. That is for laravel 4 not the 5+

<!-- Boolean Checkbox -->
<div class="form-group col-sm-2 checkbox checkbox-inline">
    <label>
        @if ($application->approved)
            {{ Form::checkbox('approved', 1, true) }} /* this returns boolean true 1 */
        @else
            {{ Form::checkbox('approved') }}  /* this returns unchecked boolean false 0 */
        @endif
        Active
    </label>
</div>

you should not need the if statement just this for checked

{{ Form::checkbox('approved', 1, true) }}

or for unchecked

{{ Form::checkbox('approved') }}

your checkbox with the if statement would only show if its checked anyway it would not tell something its checked then show you the checkbox. not sure what you were going for.

just the checkbox by itself would do what all three code examples above accomplish. you might need to use $casts in your model to show it should be boolean but I have not had to yet.

if you are looking for a good place to learn about the checkbox in laravel you could try http://laravel-recipes.com/recipes/167/creating-a-checkbox-input-field

hope it helps.

ShaileshInfyom commented 5 years ago
  1. Date filed not working while edit time issue pending here. https://github.com/InfyOmLabs/laravel-generator/issues/71
  2. Checkbox working fine