在HTML中获取和设置数据属性

时间:2015-04-09 10:09:12

标签: javascript

我有一个编辑框,定义如下:

<input class="change-handled form-control" type-id="@sub.CategoryTypeId" sub-category-id="@sub.SubCategoryId" data-id="@sub.CategoryBudgetId" style="text-align: right; width: 100%" type="number" value="@(sub.BudgetAmount.HasValue ? sub.BudgetAmount.ToString() : "")" />

在Javascript中,我成功获得了data-id值:

var dataId = $(this).attr('data-id');

我现在需要将其设置为不同的值。我在尝试:

   $(this).setAttribute("data-id", 5);

但似乎data-id永远不会被设置为我传递的值。如何设置编辑框的data-id值?

正在使用的函数的完整代码。 (注意,还没有错误检查):

$('body').on('change', 'input.change-handled', UpdateTotals);

function UpdateTotals() {
    var dataId = $(this).attr('data-id');
    var categoryId = $(this).attr('sub-category-id');
    var value = $(this).val();

    var totalExp = 0;
    var totalInc = 0;

    var $changeInputs = $('input.change-handled');

    $changeInputs.each(function (idx, el) {
        if ($(el).attr('type-id') == 2) {
            totalInc += Number($(el).val());
        }
        if ($(el).attr('type-id') == 1) {
            totalExp += Number($(el).val());
        }
    });

     $(this).val(numberWithCommas(value));

    $('#budgettedExpenseValue').text(numberWithCommas(totalExp));
    $('#budgettedIncomeValue').text(numberWithCommas(totalInc));
    $('#budgettedAvailableValue').text(numberWithCommas(totalInc - totalExp));

    $.ajax({
        url: '@Url.Action("SaveBudgetValue", "Budget")',
        type: "POST",
        contentType: "application/json",
        data: JSON.stringify({ budgetCategoryId: dataId, catgoryId: categoryId, month: 4, year: 2015, value: value }),
        cache: false,
        async: true,
        success: function (result) {

            if (result.Success == 'true') {
                $(this).attr("data-id", result.Id);

                alert("Saved! " + result.Id.toString());
            } else {
                alert("Failed");
            }
        },
        error: function () {
            alert("Oh no...");
        }

    });

在编辑类类型的编辑框之后,代码汇总所有收入框(使用type-id = 1进行装饰),并更新字段和所有费用框(type-id = 2 )并更新一个单独的字段。

然后通过json调用保存数据到我的控制器。如果它是一个新条目,则data-id将为NULL。 save方法返回保存值的主键。该值显示在我的警报中,并且应该被分配给编辑框的数据ID。但是 - 不是。

2 个答案:

答案 0 :(得分:3)

重新更新

问题是在ajax成功回调中,this不再引用该元素。

解决这个问题的两种方法,以及ES6中可用的第三种方式:

  1. this或更有用的$(this)分配给您在成功处理程序中使用的变量(以及其他地方,无需经常在其上重复调用$()元素):

    function UpdateTotals() {
        var input = $(this); // <========== Save it here
    
        // ...
    
        $.ajax({
            // ...
            success: function (result) {
                // ...
                if (result.Success == 'true') {
                    input.attr("data-id", result.Id); // <========= Use it here
    
                    alert("Saved! " + result.Id.toString());
                } else {
                    alert("Failed");
                }
            }
        });
    
        // ...
    }
    
  2. 使用Function#bind(ES5功能,但可以为真正的旧浏览器填充),使回调中的this与其外的this相同:

    function UpdateTotals() {
    
        // ...
    
        $.ajax({
            // ...
            success: function (result) {
                // ...
                if (result.Success == 'true') {
                    $(this).attr("data-id", result.Id);
    
                    alert("Saved! " + result.Id.toString());
                } else {
                    alert("Failed");
                }
            }.bind(this) // <=========== Note
        });
    
        // ...
    }
    
  3. 在ES6中,我们将有箭头函数,与普通函数不同,它继承了创建它们的上下文的this。所以在ES6中,你可以这样做:

    // **ES6 ONLY**
    function UpdateTotals() {
    
        // ...
    
        $.ajax({
            // ...
            success: (result) => {  // <==== Arrow function syntax
                // ...
                if (result.Success == 'true') {
                    $(this).attr("data-id", result.Id);
    
                    alert("Saved! " + result.Id.toString());
                } else {
                    alert("Failed");
                }
            }
        });
    
        // ...
    }
    
  4. 我倾向于#1,因为你无论如何都要重复$(this),所以做var input = $(this); 一次然后再使用{ {1}}。

    有关我博客上input的更多信息:


    原始回答更新前:

    由于您正在使用jQuery,因此您使用attr设置了一个属性,如下所示:

    this

    直播示例:

    $(this).attr("data-id", 5);
    
    var input = $("input");
    snippet.log("Before: " + input.attr("data-id"));
    input.attr("data-id", 5);
    snippet.log("After (jQuery): " + input.attr("data-id"));
    snippet.log("After (DOM): " + input[0].getAttribute("data-id"));
    snippet.log("Element's HTML (after): " + input[0].outerHTML);

    或者您可以直接使用DOM,将元素包装在jQuery包装器中:

    <input class="change-handled form-control" type-id="@sub.CategoryTypeId" sub-category-id="@sub.SubCategoryId" data-id="@sub.CategoryBudgetId" style="text-align: right; width: 100%" type="number" value="@(sub.BudgetAmount.HasValue ? sub.BudgetAmount.ToString() : "")" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
    <script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

    请注意,在任何一种情况下,即使您给出一个数字作为值,该值最终也会成为一个字符串(因为属性只存储字符串)。


    你会让人们告诉你使用data,但this.setAttribute("data-id", 5); 只是访问data属性的一种方式,即使有很多人制作那个错误。但可能对您的最终目标有用,具体取决于它是什么。 jQuery data-*函数管理与元素关联的数据缓存。值data管理的值{em>已初始化来自data属性,但data-*从不写入data属性。如果您只是尝试更新属性值,请使用data-*。如果您正在尝试执行更复杂的操作,并且将值作为属性写回元素并不重要,请查看attr的文档,看看它是否对您有用。 (一方面,值data manage可以是除字符串以外的类型。)

答案 1 :(得分:3)

您将代码放在success函数中,其中this将是某种jQuery ajax对象,而不是HTML元素。

您需要将this存储在ajax调用之外的变量中,然后使用该变量。

e.g。

var that = this;
$.ajax({

然后:

setAttribute是一个DOM方法,而不是jQuery方法。

或者:

$(that).attr("data-id", 5);

或(假设this是一个Element对象):

that.setAttribute("data-id", 5);