角度js从默认值初始化模型

时间:2012-12-07 19:27:00

标签: angularjs

假设您有一个从数据库加载值的表单。你如何初始化ng-model?

示例:

<input name="card[description]" ng-model="card.description" value="Visa-4242">

在我的控制器中,$ scope.card最初是未定义的。除了做这样的事情之外还有办法吗?

$scope.card = {
  description: $('myinput').val()
}

14 个答案:

答案 0 :(得分:236)

如果您无法修改您的应用以执行@blesh建议的操作(使用$ http或$ resource拉下JSON数据并填充$ scope),则可以使用ng-init代替:

<input name="card[description]" ng-model="card.description" ng-init="card.description='Visa-4242'">

另见AngularJS - Value attribute on an input text box is ignored when there is a ng-model used?

答案 1 :(得分:135)

这是新Angular应用程序中的常见错误。如果可以避免,则不希望将值写入服务器上的HTML。事实上,如果你可以让你的服务器完全呈现HTML,那就更好了。

理想情况下,您希望发送Angular HTML模板,然后通过JSON中的$ http下拉您的值并将它们放在您的范围内。

因此,如果可能,请执行此操作:

app.controller('MyController', function($scope, $http) {
    $http.get('/getCardInfo.php', function(data) {
       $scope.card = data;
    });
});

<input type="text" ng-model="card.description" />

如果绝对必须从服务器将值呈现到HTML中,可以将它们放在全局变量中并使用$ window访问它们:

在你的页面标题中你写出:

<head>
   <script>
       window.card = { description: 'foo' };
   </script>
</head>

然后在你的控制器中你会得到它:

app.controller('MyController', function($scope, $window) {
   $scope.card = $window.card;
});

我希望有所帮助。

答案 2 :(得分:60)

这是一个显然缺乏但很容易添加的AngularJS修复程序。只需编写一个快速指令,即可从输入字段设置模型值。

<input name="card[description]" value="Visa-4242" ng-model="card.description" ng-initial>

这是我的版本:

var app = angular.module('forms', []);

app.directive('ngInitial', function() {
  return {
    restrict: 'A',
    controller: [
      '$scope', '$element', '$attrs', '$parse', function($scope, $element, $attrs, $parse) {
        var getter, setter, val;
        val = $attrs.ngInitial || $attrs.value;
        getter = $parse($attrs.ngModel);
        setter = getter.assign;
        setter($scope, val);
      }
    ]
  };
});

答案 3 :(得分:12)

恕我直言,最好的解决方案是@Kevin Stone指令,但我必须升级它才能在各种条件下工作(f.e.select,textarea),而这一点肯定是有效的:

    angular.module('app').directive('ngInitial', function($parse) {
        return {
            restrict: "A",
            compile: function($element, $attrs) {
                var initialValue = $attrs.value || $element.val();
                return {
                    pre: function($scope, $element, $attrs) {
                        $parse($attrs.ngModel).assign($scope, initialValue);
                    }
                }
            }
        }
    });

答案 4 :(得分:7)

您可以使用自定义指令(支持textarea,选择,广播和复选框),请查看此博文https://glaucocustodio.github.io/2014/10/20/init-ng-model-from-form-fields-attributes/

答案 5 :(得分:6)

您也可以在HTML代码中使用: ng-init="card.description = 12345"

Angular不推荐使用,如上所述,您应该只使用您的控制器。

但它有效:)

答案 6 :(得分:4)

我有一个简单的方法,因为我的表格中有一些重要的验证和掩码。因此,我使用jquery再次获得我的价值并开启事件&#34;更改&#34;验证:

class SocketHandler(WebSocketHandler):
    def on_message(self, message):
        ball = json.loads(message)
        user = User(ball['identifier'])
        if ball['command'] == 'search':
            global our_mongo
            search_results = our_mongo.find({'$text':{'$search':ball['search_term']}},{'score':{'$meta':"textScore"}})
            self.write_message({
                    'command': 'search-results',
                    'results': list(search_results.sort([('score', {'$meta': 'textScore'})]).limit(10)),
            })
        elif ball['command'] == 'save-node': # hopefully this can handle both new nodes and changes to nodes
            node_dict = ball['node_dict']
            if 'importance' in node_dict.keys():
                node_dict['importance'] = int(node_dict['importance'])
            try:
                node_obj = node.create_appropriate_node(node_dict)
                print('node made.  looks like: '+str(node_obj)+'.  Now time to put it into the DB...')
                global our_mongo
                # take a look at the dependencies now
                previous_dependency_ids = [node.reduce_string(dependency) for dependency in list(our_mongo.find({"_id": node_obj.id}))[0]["_dependencies"]] # if this works, try using set() instead of list and elimination the set()s below
                print('prev deps are: '+str(previous_dependency_ids))
                our_mongo.upsert({ "_id": node_obj.id }, node_obj.__dict__)
                # take a look at the current dependencies
                current_dependency_ids = [node.reduce_string(dependency) for dependency in list(our_mongo.find({"_id": node_obj.id}))[0]["_dependencies"]] # if this works, try using set() instead of list and elimination the set()s below
                print('curr deps are: '+str(current_dependency_ids))
                update_our_DAG()
                # send an update of the graph to the user if there is a new dependency:
                for new_dependency in set(current_dependency_ids) - set(previous_dependency_ids):
                    self.request_node(new_dependency, ball, user)
                # OR IF THE SAVED NODE IS A BRAND NEW NODE, we have to include all the deps
            except Exception as error:
                # stuff didn't work, send error back to user
                print('ERROR: '+str(error))
                self.write_message({
                    'command': 'display-error',
                    'message': str(error),
                })


def update_our_DAG():
    # 1. grab nodes and edges from database
    all_node_dicts = list(Mongo("math", "nodes").find())

    # 2. create a networkx graph with the info...
    global our_DAG
    our_DAG = nx.DAG()
    for node_dict in all_node_dicts:
        node = create_appropriate_node(strip_underscores(node_dict))
        our_DAG.add_n(node)

def make_app():
    return Application(
        [
            url('/', RedirectHandler, {"url": "index.html"}, name="rooth"),
            url('/websocket', SocketHandler),
            url('/json', JSONHandler, name="jsonh"),
            url(r'/index(?:\.html)?', IndexHandler, name="indexh"),
            # captures anything at all, and serves it as a static file. simple!
            url(r'/(.*)', StaticHandler, {"path": "../www/"}),
        ],
        # settings:
        debug=True,
    )

def make_app_and_start_listening():
    # enable_pretty_logging()
    application = make_app()
    # by listening on the http port (default for all browsers that i know of),
    # user will not have to type "http://" or ":80" in the URL
    application.listen(80)
    # other stuff
    IOLoop.current().start()


if __name__ == "__main__":
    # 0. create a global mongo object for later use (for upserts in the future)
    our_mongo = Mongo("math", "nodes")

    # 1 and 2
    update_our_DAG()

    axioms = [our_DAG.n(node_id) for node_id in ['set', 'multiset', 'vertex']]

    # 3. launch!
    make_app_and_start_listening()

答案 7 :(得分:3)

正如其他人所指出的,初始化视图数据并不是一种好习惯。 但是,建议在控制器上初始化数据。 (见http://docs.angularjs.org/guide/controller

所以你可以写

<input name="card[description]" ng-model="card.description">

$scope.card = { description: 'Visa-4242' };

$http.get('/getCardInfo.php', function(data) {
   $scope.card = data;
});

这样,视图不包含数据,并且控制器在加载实际值时初始化值。

答案 8 :(得分:3)

如果你喜欢Kevin Stone的方法https://stackoverflow.com/a/17823590/584761 通过为特定标签(例如“输入”)编写指令,可以考虑更简单的方法。

app.directive('input', function ($parse) {
    return {
        restrict: 'E',
        require: '?ngModel',
        link: function (scope, element, attrs) {
            if (attrs.ngModel) {
                val = attrs.value || element.text();
                $parse(attrs.ngModel).assign(scope, val);
            }
        }
    }; });

如果你走这条路线,你不必担心在每个标签上添加ng-initial。它会自动将模型的值设置为标记的value属性。如果未设置value属性,则默认为空字符串。

答案 9 :(得分:3)

这是一种以服务器为中心的方法:

<html ng-app="project">
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <script>
        // Create your module
        var dependencies = [];
        var app = angular.module('project', dependencies);

        // Create a 'defaults' service
        app.value("defaults", /* your server-side JSON here */);

        // Create a controller that uses the service
        app.controller('PageController', function(defaults, $scope) {
            // Populate your model with the service
            $scope.card = defaults;
        });
    </script>

    <body>
        <div ng-controller="PageController">
            <!-- Bind with the standard ng-model approach -->
            <input type="text" ng-model="card.description">
        </div>
    </body>
</html>

除了$provide.value注册包含默认值的服务外,它与此问题上比较流行的答案具有相同的基本思想。

因此,在服务器上,你可以有类似的东西:

{
    description: "Visa-4242"
}

通过您选择的服务器端技术将其放入您的页面。这是一个要点:https://gist.github.com/exclsr/c8c391d16319b2d31a43

答案 10 :(得分:1)

这是上面提到的想法的更通用的版本...... 它只是检查模型中是否有任何值,如果没有,则将值设置为模型。

JS:

<select class="form-control"
        ng-options="v for (i, v) in compressionMethods"
        ng-model="action.parameters.Method"
        default-value="'LZMA2'"></select>

HTML(用法示例):

{
     "System": "2334", 
     "Id": "AP64531346-2016055553824", 
     "dtis": "106165099", 
     "Type": "Up",
     ... (in total, 112 lines per record)
}
{
     "System": "873", 
     "Id": "AP24531346-20160676553824", 
     "dtis": "1261699", 
     "Type": "Up",
     ... (in total, 112 lines per record)
}

答案 11 :(得分:0)

我尝试了@Mark Rajcok的建议。它适用于String值(Visa-4242)。 请参阅此fiddle

来自小提琴:

在小提琴中完成的同样的事情可以使用ng-repeat来完成,每个人都可以推荐。但在阅读了@Mark Rajcok给出的答案之后,我只是想对包含一系列配置文件的表单进行相同的尝试。 事情很顺利,直到我有$ scope.profiles = [{},{}];控制器中的代码。如果我删除此代码,我得到错误。 但在正常情况下,当我从服务器打印或回显html时,我无法打印$scope.profiles = [{},{}];。 是否可以像@Mark Rajcok那样对<input name="card[description]" ng-model="card.description" ng-init="card.description='Visa-4242'">这样的字符串值执行上述操作,而不必从服务器回显JavaScript部分。

答案 12 :(得分:0)

刚刚为Ryan Montgomery添加了对select元素的支持“fix”

<select class="input-control" ng-model="regCompModel.numberOfEmployeeId" ng-initial>
    <option value="1af38656-a752-4a98-a827-004a0767a52d"> More than 500</option>
    <option value="233a2783-db42-4fdb-b191-0f97d2d9fd43"> Between 250 and 500</option>
    <option value="2bab0669-550c-4555-ae9f-1fdafdb872e5"> Between 100 and 250</option>
    <option value="d471e43b-196c-46e0-9b32-21e24e5469b4"> Between 50 and 100</option>
    <option value="ccdad63f-69be-449f-8b2c-25f844dd19c1"> Between 20 and 50</option>
    <option value="e00637a2-e3e8-4883-9e11-94e58af6e4b7" selected> Less then 20</option>
</select>

app.directive('ngInitial', function () {
return {
    restrict: 'A',
    controller: ['$scope', '$element', '$attrs', '$parse', function ($scope, $element, $attrs, $parse) {
        val = $attrs.sbInitial || $attrs.value || $element.val() || $element.text()
        getter = $parse($attrs.ngModel)
        setter = getter.assign
        setter($scope, val)
    }]
}

});

答案 13 :(得分:0)

如果在mypage/id这样的URL中有init值,那么在angular JS的控制器中,您可以使用location.pathname来查找id并将其分配给您想要的模型。