【问题标题】:Controls Webpage with Knockout: Visible changes not saved使用 Knockout 控制网页:未保存可见更改
【发布时间】:2016-11-05 05:48:10
【问题描述】:

尝试使用 Excel VBA 编辑网站。编辑似乎有效,但是当我使用保存按钮时,什么都没有保存。为什么屏幕上可见的更新数据没有被保存?

此代码在 Internet Explorer 中打开一个网页,导航到我想要的位置,填写数据,所有这些都显示在屏幕上,使用各种方法,例如:

For Each objElement In objElementColl
ExtractedName = objElement.outerHTML
        
If InStr(ExtractedName, "NewPermit") > 0 Then
objElement.Checked = True

Set DropDown = objHTML.getElementById("ProjectFile-AccreditedCertifierId")
DropDown.selectedIndex = 1

objHTML.getElementsByName(ElementName)(0).Value = ValueCheck

所有工作和更改都会显示在屏幕上。我点击保存使用:

Set objElementColl = objHTML.getElementsByClassName("btn")

For Each objElement In objElementColl
    ExtractedName = objElement.outerHTML
    
    If InStr(ExtractedName, "click: save, enable:") > 0 Then
        objElement.Click
        ExtractedName = 1
        Exit For
    End If
Next

哪个运行。问题是它没有保存上面三部分的更改。

我尝试过的

  1. 暂停我的代码并手动点击保存(同样的问题)

  2. 暂停我的代码,手动更改复选框并运行代码以保存(确实保存手动更改,但不保存编码的更改

  3. 暂停代码手动换框手动保存(只保存手动换框)

从上面看,我的保存点击似乎有效,但尽管使用代码明显更改并填写了框,但可见和背景之间存在差距。

一些 HTML 源代码。是 Chrome 在检查我正在更改的元素时向我显示的内容:

    <fieldset>
        <legend>Proposal</legend>

        <div class="col-xs-12 col-sm-8 col-md-6">
            <div class="row">
                <div class="col-xs-2 form-group">
                    <label for="ProjectFile_ProposalLot">Lot</label><input class="form-control" data-bind="textInput: ProjectFile().ProposalLot" maxlength="100" name="ProjectFile-ProposalLot" type="text" />
                </div>
                    <div class="col-xs-2 form-group" data-bind="visible: ProjectFile().StateId() != 7 && ProjectFile().StateId() != 5">
                        <label data-bind="text: ProjectFile().ProposalDpLabel()"></label>
                        <input class="form-control" data-bind="textInput: ProjectFile().ProposalDp" maxlength="100" name="ProjectFile-ProposalDp" type="text" />
                        </div>

我搜索了该页面的源代码。我相信这可能很重要,但我不是 HTML 编码器。我把它缩短了一点

var ProjectFileEditViewModel=(function(){__extends(ProjectFileEditViewModel,ViewModel.Model);function ProjectFileEditViewModel(){ProjectFileEditViewModel.__super__.constructor.apply(this,arguments);};ProjectFileEditViewModel.prototype.fields=function(){return {"Id":new ViewModel.NumberField(0),"StateId":new ViewModel.NumberField(0),"DefaultOfficeAddressId":new ViewModel.ObservableField(),"Name":new ViewModel.ObservableField(),"ExistingApprovalDate":new ViewModel.DateField("DD/MM/YYYY"),"ProjectClosed":new ViewModel.ObservableField(),"ProposalAddress":new ViewModel.ObservableChildField(exports.AddressViewModel,this),"Zoning":new ViewModel.ObservableField(),"ProposalLot":new return ProjectFileEditViewModel;})();if(exports.ProjectFileEditViewModel==null)exports.ProjectFileEditViewModel=ProjectFileEditViewModel;

还有这个:

Buildaform.model=new Buildaform.ProjectPageViewModel({ ... ,"ProposalLot":null .... }

我认为最后一个与它有关。不知道能不能改。

我不能公开发布网站地址或源代码。

【问题讨论】:

  • 足够公平......会做
  • 我过去也遇到过类似的问题。使用浏览器开发人员工具检查 html DOM,我发现每当我手动更改表单上的值(比如说一个带有 id:input1 的值)时,它都会“镜像”到另一个元素在不可见的 DOM 上(比如说一个带有 id:input1_value 的 DOM)。然而,每当我以编程方式更改 input1 的值时,input1_value (这是表单使用的值)都不会更改。解决方案是在提交表单之前以编程方式更改这两个元素的值。
  • 导航到网页,右键单击输入字段之一并选择检查元素,这将在开发人员工具上显示 DOM。现在回到页面并在输入中输入一个值,您会注意到相关 DOM 元素的变化。然后,在 DOM 视图中,搜索 (Ctrl+f /Cmd+f) 以查找您在输入中输入的值,并检查是否在 DOM 上的多个标签上找到它。
  • 我不知道如何更改它,但也许对数据绑定进行一些研究会有所帮助。另一个问题讨论它:How to Implement DOM Data Binding in JavaScript.
  • 我假设您获得了带有CreateObject("InternetExplorer.Application") 的IE 引用?您对页面引用的所有 javascript 文件实际加载的信心如何?

标签: javascript excel vba knockout.js dom-events


【解决方案1】:

由于相关网站无法共享,我可以想出一组提示来尝试:

如果网站将实现一个简单的(纯)HTML 表单来发送 POST 请求,那么您的解决方案就可以了。但是看看你分享的 HTML

<label data-bind="text: ProjectFile().ProposalDpLabel()"></label>

data-bind 已经暗示图书馆正在收集/发送数据。 (例如 Knockout 正在使用该属性)。这个库现在可能会在某个地方收集数据,它可能会被 JavaScript 中的“点击”或“按键”事件触发。然后可以将收集到的信息存储在 GCSDC 建议的隐藏 DOM 元素中,或直接存储在 JavaScript 变量中。

我现在的建议是通过检查 HTML 源来找出此页面上使用的 JavaScript 框架。在某些时候应该有一个

<script src="<fancy js framework>.js"></script>
HTML 中的

标记,它应该为您提供框架的名称。 (这种标签实际上可以有多个,包括自定义的 JavaScript 文件。这些标签不必在 HTML 文档的开头,可以分散在各处,因此您可能需要在其中搜索 script HTML 文档。其中一个应该是发送请求的主框架。如果您不确定它会是哪一个,您必须谷歌所有这些并找出。)

然后,在框架文档的帮助下,研究如何在此页面上的 JavaScript 代码中发送 POST(可能是 Ajax)请求。然后,通过在此页面上执行 VBA 中的自定义 JavaScript 来发送请求; this 帖子中显示了如何做到这一点。

或者,您可以尝试在表单输入上触发单击(或按键)事件,以使框架相信您确实输入了它;这个post 显示了如何做到这一点,但这可能不适用于所有情况。

【讨论】:

    【解决方案2】:

    根据您的评论:

    1. 暂停我的代码,手动更改复选框并运行代码以保存 (确实保存手动更改,但不保存编码的更改

    似乎问题出在代码设置表单控件上,而不是代码单击保存按钮。

    这似乎是一个与 VBA 无关的问题,但与 knockout 的行为有关 - 请参阅 this SO post。相关评论是:

    您的问题是 ko 订阅了已检查绑定中的 click 事件:

    该帖子中的提问者遇到了与您类似的问题 - 他们正在尝试检查一个复选框(以更改视图),但它没有更新视图模型或底层模型本身. Knockout 是一个MVVM 框架。

    您的问题是您的手动更改提交是因为您在通过浏览器中的点击执行操作时执行点击并更改,但您的编程方法仅对表单进行更改控制,而不是先点击。

    那么,如何通过 IE 通过 VBA 自动化来解决这个问题?

    基于我上面引用的帖子中的解决方案,加上方法here,我将冒险使用下面的代码作为可能的解决方案,但请注意它未经测试...

    基本上,您需要“单击”要更改的表单元素 - 然后更新控件值。希望“点击”位将意味着淘汰视图模型根据“更改”进行更新,并从那里将模型数据写入数据库(或其他):

    您的复选框示例:

    If InStr(ExtractedName, "NewPermit") > 0 Then
    // hopefully this will get knockout to apply the required binding before your change the value
    objElement.Click
    objElement.Checked = True
    

    您的下拉示例:

    Set DropDown = objHTML.getElementById("ProjectFile-AccreditedCertifierId")
    // hopefully this will get knockout to apply the required binding before your change the value
    Dropdown.Click
    DropDown.selectedIndex = 1
    

    希望对您有所帮助 - 完全是 3 管问题!祝你好运。

    【讨论】:

    • 嗯……就在我们接近答案的时候,老板决定改变系统,我不再需要答案了。然而,我将在下周末重新审视这个并报告它是否有效。使用它我学到了很多东西,而且非常有趣。感谢您的帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-20
    • 1970-01-01
    • 1970-01-01
    • 2021-10-28
    相关资源
    最近更新 更多