可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have controls that are model tied to ASP.net MVC5
@Html.TextBoxFor(model => model.OriginLocation.City, new { @class = "form-control", data_ng_model = "address1.City", test_change = "" })
So when the page loads the value of text box input is bound and should display value coming from service with Razor bound controls, latter i can manipulate that value which changes angular model for this control.
What i have is textbox loads empty.
I can see the value when I view source but its not displayed.
<input class="form-control ng-pristine ng-valid" data-ng-model="address1.City" data-val="true" data-val-length="The field City must be a string with a maximum length of 50." data-val-length-max="50" id="OriginLocation_City" name="OriginLocation.City" test-change="" type="text" value="Manheim">
js fragment
app.controller('LocationCtrl', ["$scope",
function ($scope) {
$scope.address1 = { Label: 'address1' };
回答1:
ngModel
has precedence over the value that is originally set (it's setting the value to "" because the model doesn't exist). Take a look here...
http://jsfiddle.net/yApeP/
But you can specify a value using ngInit
...
http://jsfiddle.net/D7vh7/
Which means you can use ngInit
when generating the textbox...
@Html.TextBoxFor(model => model.OriginLocation.City,
new { @class = "form-control",
data_ng_model = "address1.City",
test_change = "",
data_ng_init = string.Format("address1.City = '{0}'", Model.OriginLocation.City.Replace("'", @"\'")) })
回答2:
Angular will replace the contents of the text box with the value from its own model, which means you need to populate the Angular model. This can be achieved quickly by serializing your MVC model (or part of it) into your Angular model:
app.controller("TestController", function($scope) {
$scope.person = @Html.Raw(JsonConvert.SerializeObject(Model.Person));
});
You can then render your MVC controls in the view like this:
@Html.TextBoxFor(x => x.Person.Name, new { ng_model = "person.Name" })
回答3:
Considering the answer by @Alan, I found a way that is "kind of" clean. Well that is the solution that I am using when creating ASP MVC Projects with Angular.js.
Instead of serializing the model inside the Angular controller (which would require to declare the controller inside of the Razor template), I serialize it in a global variable in each of my razor template like :
<script>
//Add the namespace you want to not poluate the global namespace
window.Model = @Html.Raw(JsonConvert.SerializeObject(Model))
</script>
I also use the property attribute [ScriptIgnore]
for the properties I don't want to serialize (that could cause circular references).
public class Classroom {
public string Title {get;set;}
[ScriptIgnore]
//Students could be associated to classroom, and that classroom has
// students etc. If you want those properties, create a new object in a
// PageView withtout circular references
public List<Students> Students {get;set;}
}
After that, inside of my controllers, I simply do something like
app.controller("TestController", function($scope) {
$scope.model = window.Model;
//My other stuff...
});
Also, that way your angular Model always have the SAME properties has your ASP MVC Model.
回答4:
One clean way to solve this life-cycle issue is by writing a directive for the "value" attribute for the input.
At first you can simply write the Razor's model value in yout input element by using the basic Razor syntax.
<input type="text" class="form-control" id="name" name="name" value="@Model.Name" data-ng-model="myModel.name">
That will write the value of the @Model.Name in the input when the page is rendered, but this value will be replaced by empty values when Angular starts the bindings.
So you can write a directive, and on the "link" method you can play with the ngModel in order to keep the value that was present in the input before Angular cleans it.
(The property 'prioriy: 0' indicates that the directive should be compiled as soon as possible)
function inputDirective(){
return {
restrict:'A',
priority: 0,
require: 'ngModel',
link: function(scope, elem, attrs, ngModelCtrl){
ngModelCtrl.$setViewValue($(elem).val());
}
};
}
That should restore the value written by Razor in your Angular's model