【问题标题】:Why can't AngularJS view send data to this re-usable service?为什么 AngularJS 视图不能将数据发送到这个可重用的服务?
【发布时间】:2023-03-16 17:38:02
【问题描述】:

AngularJS 应用程序需要重用多个自定义对象。我担心创建难以维护的杂乱、冗余代码,因此我将可重用代码移至一个服务,该服务可以为每个视图简明地注入到控制器中,然后直接从每个 html 视图调用,而不会使控制器变得混乱代码。

下图说明了服务someclass.js 将如何被重用,以及为什么将尽可能多的代码隔离在一个地方很重要:

我开发的代码可以在我的 devbox 上部分完成,我有 posted the code to a plnkr。 (感谢@shakir 让这个 plnkr 重新创建问题。)我还包括下面的代码。

虽然单击表单提交按钮确实会调用服务中的表单处理程序方法,但问题是应该包含表单数据的对象在应该处理表单数据的 someclass.method1() 方法中未定义. 需要对下面的代码进行哪些具体更改,以便可以在服务的表单处理方法中操作表单中用户提交的数据的值?

视图和服务之间(通过控制器)通信的完整要求是:

1.) someclass.prop1 可以在视图中打印其值(这在下面的代码中有效),并且

2.) confirmFormng-submit 可以直接调用 someclass.method1 作为处理程序,从而最小化 someroute.js 中的代码(这发生在下面的代码中,但是应该包含的对象someclass.somemethod1() 运行时未定义表单数据)


plnkr 代码:


这里是the plnkr @JoaozitoPolo 建议的服务的调用。当前版本能够从视图中调用someclass.method1(),但表单数据没有传递到函数中。所以我们需要弄清楚如何将表单数据传递给函数。


此处还显示代码:


(在我的devbox上)将someview.html的属性和方法与someclass.js连接起来的代码(但在函数调用期间不会将表单中的数据发送到someclass.js)如下:

这是someclass.js的代码:

angular
.module('someclass', ['ngCookies'])
.service('someclass', ['$rootScope', '$http', '$cookies', function($rootScope, $http, $cookies){

this.prop1 = $cookies.get('test1');
this.prop2 = 'nothing';
this.resultphone = {};

this.method1 = function(isValid, resultphone) {
    if(isValid){
        var funcJSON = resultphone;
        funcJSON.wleadid = '1';//resultphone is undefined in debugger here
        alert("just a filler to add breakpoint for debugger");
        $http.post('/some-test-service', funcJSON).then(
            function(response) {
                prop2 = response.data.content;
            }
        );
    }
};

}]);

这是someroute.js的代码:

angular
.module('someroute', ['someclass'])
.controller('someroute', function($scope, someclass) {

    $scope.someclass = someclass;

});

这里是someroute.html

someclass.prop1 is: {{someclass.prop1}} <br>
someclass.prop2 is: {{someclass.prop2}} <br>
<div ng-show="someclass.prop1!='yes'">
    <h1>someclass prop1!</h1>
    <div ng-include="'someroute_start.html'"></div>
</div>
<div ng-show="someclass.prop1=='yes'">

    <div ng-show="someclass.prop2=='showfirst'">
        <h1>Include start.</h1>
        <div ng-include="'someroute_first.html'"></div>
    </div>

    <div ng-show="someclass.prop2=='showsecond'">
        <h2>Include second.</h2>
        <div ng-include="'someroute_second.html'"></div>
    </div>

</div>

这里是someroute_start.html,里面包含了需要someclass.js处理的表单:

    <form name="confirmForm" ng-submit="someclass.method1(confirmForm.$valid)" novalidate>
        Enter some value: 
        <input type="text" name="phonenum1" ng-model="resultphone.phonenum1" required />
        <button type="submit" ng-disabled="confirmForm.$invalid" >Submit</button>
    </form>

为了完整起见,我包括someroute_first.html,很简单:

<h3>Showing first! </h3>

还有someroute_second.html,就这么简单:

<h3>Showing second! </h3>

应用程序的主控制器是hello.js,我将其包括在此处,以防部分解决方案包括初始化someclass

angular
    .module('hello', [ 'ngRoute', 'someclass', 'home', 'someroute', 'navigation' ])
    .config(

            function($routeProvider, $httpProvider, $locationProvider) {

                $locationProvider.html5Mode(true);

                $routeProvider.when('/', {
                    templateUrl : 'home.html',
                    controller : 'home'
                })
                .when('/someroute', {
                    templateUrl : 'someroute.html',
                    controller : 'someroute'
                }).otherwise('/');

                $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

            }
    )

为了完整起见,index.html 按如下方式加载模块:

<!DOCTYPE html>
<html>
  <head>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular-route.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/css/bootstrap.min.css"></script>
    <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" />

    <link href="style.css" rel="stylesheet"/>
    <style type="text/css">
    [ng\:cloak], [ng-cloak], .ng-cloak { display: none !important; }
    </style>
  </head>

  <body class="ng-cloak" ng-cloak="" ng-app="hello">
    <div class="container" ng-controller="navigation">
      <ul role="tablist" class="nav nav-pills">
        <li ng-class="{active:tab('home')}">
          <a href="#/">home</a>
        </li>
        <li ng-class="{active:tab('someroute')}">
          <a href="#/someroute">some route</a>
        </li>
      </ul>
    </div>
    <div class="container" ng-view=""></div>

    <script type="text/javascript" src="someclass.js"></script>
    <script type="text/javascript" src="home.js"></script>
    <script type="text/javascript" src="someroute.js"></script>
    <script type="text/javascript" src="navigation.js"></script>
    <script type="text/javascript" src="hello.js"></script>
  </body>
</html>

同样,以上所有代码都包含在a bare minimum excerpt of code required to reproduce the problem at this plnkr 中。 那么需要对 1.) 使 plnkr 工作和 2.) 将表单数据传递到对 someclass.method1() 的调用进行哪些​​具体更改?

【问题讨论】:

  • &lt;input type="text" name="phonenum1" ng-model="resultphone.phonenum1" required /&gt; 应该是&lt;input type="text" name="phonenum1" ng-model="someclass.resultphone.phonenum1" required /&gt;
  • @shakib 谢谢,但更改该行并没有解决问题。 resultphonefuncJSONsomeclass.method1() 中未定义,并且在 eclipse 调试器在该方法中给出 funcJSON.wleadid = '1'; 行后程序简单地停止运行。也许如果我们能让 plnkr 工作,它可能更容易调试。在您的建议之后,在我的 Firefox 开发箱上运行的版本按照此评论中的描述工作。还有其他想法吗?
  • 添加了ngCookies 模块脚本引用并更改了someclass.js 中的cookie 代码。运行 plunkr plnkr.co/edit/JInT1u1n79M6HNW7qtNZ
  • @shakib 您还添加了var $this = this;,这是解决方案的关键部分。

标签: javascript angularjs


【解决方案1】:

我看起来你的 plunker 更新了。太棒了。

只是 someclass.js 的一个问题...您需要在内部函数中使用“$this”变量来访问正确的范围:

$http.post('/some-test-service', funcJSON).then(
    function(response) {
        $this.prop2 = response.data.content;
    }
);

【讨论】:

  • 您的代码导致prop2 的值在视图中更新,使其等于showfirst,但视图不会以任何其他方式更新,这意味着表单仍然可见,并且包含文件不会改变。为了启用这个工作示例的最后一部分,我需要进行哪些更改?
  • 我将把它标记为已接受并 +1,因为您回答了如何将数据从视图获取到服务的问题。但是,我发布了一个不同的问题,关于如何从类似的服务中获取数据以刷新视图。您对此问题的回答不会导致视图更新,并且此 OP 中的代码不会让数据真正更新,因为此 OP 依赖于断开连接的后端服务。你愿意评论另一个问题吗?这是链接:stackoverflow.com/questions/35167161/…
  • 我将评论另一个问题。
【解决方案2】:

表单提交功能是否正确?

我不确定我是否让你们放松,但如果问题在于将表单数据传递给 someclass.method1,我会尝试这样的事情:

ng-submit="someclass.method1(confirmForm.$valid,someclass.resultphone)"

而不是这个:

ng-submit="someclass.method1(confirmForm.$valid)"

someclass.method1 定义看起来像

this.method1 = function(isValid, resultphone) {...}

对吗?

【讨论】:

猜你喜欢
  • 2012-05-19
  • 2016-07-06
  • 1970-01-01
  • 2014-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-22
相关资源
最近更新 更多