简体   繁体   中英

How to use javascript to hide sections of a CakePHP form

I am trying to use javascript to display or hide a section of a CakePHP form, based on the value of a checkbox.

I am enhancing an existing CakePHP form which already has this functionality working for one section of the form and am adding another section to the form which needs similar functionality. I am new to javascript programming and looking at the existing code I am unclear on the naming convention that it uses to access the field values of the CakePHP form.

Here is the code which already works to display or hide a section of the form:

CakePHP view code which builds the form:

echo $this->Form->create('Book', array('type' => 'file', 'id' => 'BookForm'));
echo $this->Form->input('is_part_of_series', array(
    'label' => __('Part of Series', true),
    'type' => 'checkbox',
    'id' => 'partOfSeries'));
echo '<div class="series">';
echo $this->Form->input('series_title', array(
    'label' => __('Series Name', true)));
echo $this->Form->input('series_sequence', array(
    'label' => __('Series Sequence', true)));
echo '</div>';
echo $this->Form->submit('Submit', array('class' => 'dark button inline', 'div' => false));
echo $this->Form->end();

Javascript code which displays or hides the "series" div:

App.booksAdd = {
    init: function () {
    var self = this;

    if ($('#BookSeriesTitle').val() != "" || $('#BookSeriesSequence').val() != "") {
        $('#partOfSeries').attr('checked', "checked");
    }

    this.hideSeries();

    $('#partOfSeries').click(function() {
        self.hideSeries();
    });

    hideSeries: function () {
        if ($('#partOfSeries').attr('checked')) {
            $('div.series').show();
        } else {
            $('div.series').hide();
        }
    }
}

This code initializes the checked status based on whether the series title and series sequence values are empty. I don't understand how the variable names #BookSeriesTitle and #BookSeriesSequence are derived from the series_title and series_sequence names on the CakePHP form. I searched all the code for these names, but there are no other instances of these names anywhere in the code.

This is the additional code I am adding:

CakePHP view code which builds the form:

$hasAReleaseDate = empty($book['Book']['sales_start']) ? '0' : '1';
echo $this->Form->input('has_release_date', array(
    'label' => __('Specify release date', true),
    'type' => 'checkbox',
    'checked' => $hasAReleaseDate,
    'id' => 'hasReleaseDate'));
echo '<div class="releasedate">';
echo $this->Form->input('sales_start', array(
    'label' => __('Release Date', true),
    'dateFormat' => 'YMD',
    'minYear' => '1980', 
    'maxYear' => date('Y') + 1,
    'type' => 'date'));
echo '</div>;

New javascript code which displays or hides the "releasedate" div:

if (document.getElementById("hasReleaseDate").val() == "1") {
    $('#hasReleaseDate').attr('checked', "checked");
}

this.hideReleaseDate();

$('#hasReleaseDate').click(function() {
    self.hideReleaseDate();
});

hideReleaseDate: function () {
    if ($('#hasReleaseDate').attr('checked')) {
        $('div.releasedate').show();
    } else {
        $('div.releasedate').hide();
    }
}

The new checkbox is functioning correctly to hide and show the "releasedate" div each time I click on the checkbox. However when the page is initially displayed the section is not properly displayed or hidden based on the initial value of the data.

I believe the problem is on the line:

if (document.getElementById("hasReleaseDate").val() == "1") {

because it is not properly referencing the initial state of the hasReleaseDate checkbox field.

The previous code that implements the series section didn't initialize the javascript variable #partOfSeries checked state using the form checkbox field, but instead checked the values of the two fields which get displayed when the checkbox is set.

For the new code this won't work because CakePHP defaults the date field to today's date if it was not previously set, so it always has a non-empty value. For the new code I need the javascript to initialize its checked status based on the checked status of the form hasReleaseDate field.

I experimented trying to use a similar reference to the form data "#BookHasReleaseDate" like the exiting code does, but as it was not working and I don't understand how the naming works, I then switched to what appeared to be more common naming in the code samples I found "document.getElementById("hasReleaseDate")". I couldn't get it working either way, and I have not been able to determine if my problem is a problem correctly referencing the form checkbox, or a problem with the logic which attempts to compare if the checked value is '1'.

If someone understands how the #BookSeriesTitle naming convention references the CakePHP form series_title field I would appreciate learning how this works, as well as help in coding the correct way to reference the new hasReleaseDate field to initialize the checked status of the javascript $hasReleaseDate variable.

Just drop the if from your Javascript:

this.hideReleaseDate();

$('#hasReleaseDate').change(function() {
    self.hideReleaseDate();
});

hideReleaseDate: function () {
    if ($('#hasReleaseDate').attr('checked')) {
        $('div.releasedate').show();
    } else {
        $('div.releasedate').hide();
    }
}

The hideReleaseData function does what you need it to. If the checkbox is checked, show the release date div. If not, hide it. CakePHP takes care of setting the initial checked state of the checkbox.

Also, you'll want to listen the change event instead of click . This catches keyboard toggles as well (ie, tabbing to the element and hitting space).


CakePHP naming conventions: [Model][FieldName]. So, for the series title:

echo $this->Form->input('series_title', array(
    'label' => __('Series Name', true)));

Look at the field name, series_title . I know the label is "Series Name", but that's not relevant. CamelCase it, so it becomes SeriesTitle. Then, prepend the model name, Book: BookSeriesTitle. This becomes the ID of the element ( #BookSeriesTitle in the Javascript), unless you specify the ID yourself.

For example:

echo $this->Form->input('is_part_of_series', array(
    'label' => __('Part of Series', true),
    'type' => 'checkbox',
    'id' => 'partOfSeries'));

Normally, this element would have the ID BookIsPartOfSeries , but a manual ID, partOfSeries , is specified instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM