簡體   English   中英

使用JQuery為准備好文檔時的依賴選擇設置值

[英]Use JQuery to set value for dependent select upon document ready

Rails 4.0.3,Ruby 2.0.0

地板是一個依賴選擇。 在選擇建築物之前,它的內容,樓層數是未知的。 但是,這是在edit(update)表單中觸發的。 因此,建築物和地板是已知的。 我正在嘗試在JQuery中設置當前值。 我獲得建築物索引並單擊建築物。 此時,此處引用的編輯表單將顯示建築物名稱。 它還應該顯示地板,但那沒有發生。 它僅顯示提示。 建築物事件觸發時如何觸發樓層事件,以便同時選擇兩個當前值?

$(document).ready(function () {
    ...
    });
    $("select[name='item[building_id]']").change(function () {
        $.getJSON("/floors", {building: $(this).val()}, function (data) {
            var options_html = ['<option value="">Floor?</option>'];
            $.each(data, function (index, floor) {
                if (index = 0) {options_html.push('<option value="">Floor?</option>');}
                options_html.push("<option value='" + floor.id + "'>" + floor.name + "</option>");
            });
            $('select#item_floor_id').html(options_html.join('')).prop('disabled', false);
        });
    });
    $("select[name='item[building_id]']").ready(function () {
        var building = $('#item_building_id').attr("value");
        $("#item_building_id").val(building).trigger("change");
    });
    $("select[name='item[floor_id]']").ready(function () {
        var floor = $('#item_floor_id').attr("value");
        $("#item_floor_id").val(floor);
    });
});

編輯我不是JavaScript / JQuery專家,但是我不明白為什么這不起作用並且有同樣的問題。 它會在選擇列表完成之前嘗試選擇樓層。 如果設置了斷點然后恢復,則可以正常工作...

$(document).ready(function () {
    ...
    });
    $("select[name='item[building_id]']").change(function () {
        $.getJSON("/floors", {building: $(this).val()}, function (data) {
            var options_html = ['<option value="">Floor?</option>'];
            $.each(data, function (index, floor) {
                if (index = 0) {options_html.push('<option value="">Floor?</option>');}
                options_html.push("<option value='" + floor.id + "'>" + floor.name + "</option>");
            });
            $('select#item_floor_id').html(options_html.join('')).prop('disabled', false);
        });
        var floor = $('#item_floor_id').attr("value");
        $("#item_floor_id").val(floor);
    });
    $("select[name='item[building_id]']").ready(function () {
        var building = $('#item_building_id').attr("value");
        $("#item_building_id").val(building).trigger("change");
    });
});

您的問題和嘗試的解決方案有一些問題。 這個問題在現代Web應用程序中很常見,有幾種解決方案。

如果我正確理解這一點,那么您會有大量的HTML,其中包含一個在編輯上下文中的表單,該表單中的某些字段在呈現HTML時已經由服務器代碼(紅寶石)填充,包括兩個選擇字段building_id和floor_id。

您需要一些將在這些選擇的更改事件上執行的javascript代碼。 但是,我假設您還希望該代碼在最初加載頁面時運行,並根據服務器已預設的值運行。

首先,您正在濫用.ready()。 盡管它可以作為所有jquery對象上的方法使用,但實際上除了文檔元素(在此情況下)之外,在任何其他元素上調用它實際上都沒有任何意義。 通常,每頁只需要一個.ready()調用,並且該調用應用於分配事件處理程序,初始化對象等。

其次,您無需手動觸發select onchange事件處理程序。 它可以作為一種選擇,但是它是一種駭人聽聞的做事方式,通常顯示出代碼的分解不佳。 避免在事件處理程序中做太多事情。 將回調限制為從事件收集和存儲相關數據,然后調用另一個方法來完成實際工作。 這樣,您就可以從其他地方調用work方法,而無需假裝觸發select事件。

您的問題不是一件容易的事,因為您想響應兩個單獨的數據源-初始填充的形式以及用戶更改值時的操作。 它們的處理方式應該不同,我們不應該假裝服務器正在單擊選擇下拉列表。

$(document).ready(function () {    
    // do stuff with the prepopulated data
    updateBuildingName();
    updateFloorName();

    // set up the event handlers for the user changing values
    $('select#building_id').on('change', buildingIDChanged);
    $('select#floor_id').on('change', floorIDChanged);
});

function updateBuildingName() {
    var building_id = $('select#building_id option:selected').val();
    var building_name = 'None';
    if (building_id) {
        building_name = $('select#building_id option:selected').text();
    }
    $('#building_name').text(building_name);
}

function updateFloorName() {
    var floor_id = $('select#floor_id option:selected').val();
    var floor_name = 'None';
    if (floor_id) {
        floor_name = $('select#floor_id option:selected').text();
    }
    $('#floor_name').text(floor_name);
}

function buildingIDChanged() {
    var building_id = $(this).val();
    fetchFloorList(building_id).then(function () {
        updateBuildingName();
        updateFloorName();
    });
}

function floorIDChanged() {
    updateFloorName();
}

function fetchFloorList(building_id) {
    $('#floor_id').prop('disabled', 'disabled');
    $('select#floor_id').html('<option value="0">Loading data...</option>');
    return $.ajax({ ... })
    .then(function (data) {
        populateFloorList(data);
    });
}    

function populateFloorList(data) {
    var options_html = ['<option value="">Select a floor...</option>'];
    $.each(data, function (index, floor) {
        options_html.push("<option value='" + floor.id + "'>" + floor.name + "</option>");
    });
    $('select#floor_id').html(options_html);
    $('#floor_id').prop('disabled', '');
}    

編輯:和一個jsfiddle

我認為諾言仍然是您最好的選擇,只需將其附加到$ .getJSON()隱式創建的諾言中,然后再加上.then(function(){// do stuff})); .then()函數僅在$ .getJSON中的success()完成后才會觸發。

$(document).ready(function () {
...
});
$("select[name='item[building_id]']").change(function () {
    $.getJSON("/floors", {building: $(this).val()}, function (data) {
        var options_html = ['<option value="">Floor?</option>'];
        $.each(data, function (index, floor) {
            if (index = 0) {options_html.push('<option value="">Floor?</option>');}
            options_html.push("<option value='" + floor.id + "'>" + floor.name + "</option>");
        });
        $('select#item_floor_id').html(options_html.join('')).prop('disabled', false);
    }).then(function() {
        var floor = $('#item_floor_id').attr("value");
        $("#item_floor_id").val(floor);
    });
});
$("select[name='item[building_id]']").ready(function () {
    var building = $('#item_building_id').attr("value");
    $("#item_building_id").val(building).trigger("change");
});

});

我已經在幾種不同的情況下對上述內容進行了測試,並且在所有情況下,都會在填充選擇后執行promise。

嘗試在建築物上設置.promise()延遲對象,以確保在呼叫地板之前首先完成:

$(document).ready(function () {
    $("select[name='item[building_id]']").change(function () {
        $.getJSON("/floors", {building: $(this).val()}, function (data) {
            var options_html = ['<option value="">Floor?</option>'];
            $.each(data, function (index, floor) {
                if (index = 0) {options_html.push('<option value="">Floor?</option>');}
                options_html.push("<option value='" + floor.id + "'>" + floor.name + "</option>");
            });
            $('select#item_floor_id').html(options_html.join('')).prop('disabled', false);
        });
    });
    $("select[name='item[building_id]']").ready(function () {
        var building = $('#item_building_id').attr("value");
        $("#item_building_id").val(building).trigger("change");
    }).promise().done(function () {
        $("select[name='item[floor_id]']").ready(function () {
            var floor = $('#item_floor_id').attr("value");
            $("#item_floor_id").val(floor);
        });
    });
});

這行是關鍵: .promise().done(function () {

這將確保在加載地板之前先加載建築物。

這里的文件

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM