Cannot find control with path: angular2 - angular2-forms

I'm working on a model driven form and I can't get it to add items to a list being displayed with ngFor. I'm currently getting an error when trying to iterate the list.I tried all solutions available.
Error
Cannot find control with path: 'categories -> 0'
ts file
private categories : any= [{name: 'Strict',selected : false},
{name: 'Moderate',selected : true},
{name: 'Flexible',selected : true}];
let allCategories: FormArray = new FormArray([]);
for (let i = 0; i < this.categories.length; i++) {
let fg = new FormGroup({});
fg.addControl(this.categories[i].name, new FormControl(this.categories[i].selected))
allCategories.push(fg)
}
form initialization
categories: allCategories,
Html part
<div formArrayName="categories">
<div *ngFor="let category of categories; let i=index">
<span formGroupName="{{i}}">
<label>
<input type="checkbox" formControlName="{{category.name}}"/>
{{category.name}}
</label>
</span>
</div>
</div>

#Jadoon, I suppose, #DineshArun meant that he wants to list all categories using reactive approach and uses for that FormArray with FormGroups for each category.
The problem is that Angular usually assigns array index as group name by default 0, 1...
But in #DineshArun's case that doesn't work. And in mine case it didn't too, but I've found the solution.
First of all, look at this question and it's marked answer. Rewrite the filling in of your formArray that way, and then assign to formControlName the raw name of the control, which you pointed in your patch() method.

Related

knockoutmvc - unable to parse bindings

I have an ASP.NET MVC site and I am trying to get knockout-mvc working with it.
I have created a View Model in the C# code called Refund that contains among other things a Voucher called Vouchertype and a List<Country> called Countries. Voucher has a variable of type int called VoucherNumber
This View Model is passed into a strongly defined view Refund\Index
I am trying to get knockout-mvc to bind the values in Refund.Voucher.VoucherNumber to a textbox, and the Values in Refund.Countries to a drop-down list. On the controller I have hardcoded the values of Voucher.Vouchernumber and added two countries to the Country list.
Here is my View Code:
#using Resources
#using PerpetuumSoft.Knockout
#model MVC.Models.RefundViewModel
#{
var ko = Html.CreateKnockoutContext();
}
<div id="refundformcontainer">
<div id="headersection">
<div id="pagetitlecontainer">#Language.RefundVouchers</div>
<div id="helpercontainer">
<label id="lblhelper">To begin enter a voucher number or scan a barcode</label>
</div>
</div>
<div id="vouchercontainer">
<div id="voucherdetailscontainer">
<h5>#Language.VoucherDetails</h5>
<div id="vouchernumbercontainer" class="initialvoucherfield">
#Html.LabelFor(x=>x.Voucher.VoucherNumber)
#ko.Html.TextBox(x=>x.Voucher.VoucherNumber)
</div>
<div id="countrycontainer" class="initialvoucherfield">
#Html.LabelFor(x=>x.Voucher.Country)
<select ko.Bind.Options(x=>x.Countries).OptionsText("Name").OptionsValue("CountryId").Value(x=>x.Voucher.CountryId) ></select>
</div>
</div>
</div>
</div>
#ko.Apply(Model);
When the page loads, neither controls are bound to.
When I look at the generated source the following code is generated
<script type="text/javascript">
var viewModelJs = {"Refund":null,"Voucher":{"VoucherId":0,"VoucherNumber":123456789,"Country":null,"CountryId":0,"Retailer":null,"RetailerId":0,"PurchaseDate":"0001-01-01T00:00:00","CustomsStampDate":null,"InvoiceNumber":"","LineItems":[],"TotalPurchasePrice":0.0},"Countries":[{"CountryId":380,"Name":"Italy"},{"CountryId":724,"Name":"Spain"}]};
var viewModel = ko.mapping.fromJS(viewModelJs);
ko.applyBindings(viewModel);
</script>
knockout-2.2.0.js and knockout.mapping-latest.js are both included in the page
The error I am getting is
0x800a139e - JavaScript runtine error: Unable to parse bindings
Message: [Object Error]
Bindings value: Voucher().VoucherNumber
I then changed the Refund View model so it had a property VoucherNumber and had the textbox reference this instead of the Voucher.VoucherNumber property
#ko.Html.TextBox(x=>x.VoucherNumber)
When I ran this I got the same unable to parse bindings error, but this time for the country
Bindings value: options : Countries, optonsText : Name, optionsValue : CountryId
Does anybody have any idea what is causing this?
i think, this should work.
<select #ko.Bind.Options(x=>x.Countries).OptionsText("'Name'").OptionsValue("'CountryId'").Value(x=>x.Voucher.CountryId) ></select>

Nested form trouble using Rails and AngularJS

I am fairly new to js and angular but I was trying to get a Rails app working after watching Ryan Bates's railscast on Rails+AngularJS (http://railscasts.com/episodes/405-angularjs?autoplay=true).
I believe what I want to do is fairly simple: I have a Place model that has many Phones and I want to dynamically be able to add and save phones when creating a new Place. This type of nested form is fairly easy in Rails alone (with js only creating a new field element when a user adds a Phone), but I want to do this in Angular.
I suppose my question then breaks down into two:
1) What is the best practice of creating nested forms in Rails+AngularJS (or even forms in general)? Right now I am passing every model to Angular via JSON but is this the best way?
My second question refers to the following code.
I've attempted to do this and I am able to save a Place in angular:
places_controller.rb
respond_to :json
def create
respond_with Place.create(params[:place])
end
_form.html.erb
<div class="container-fluid" ng-controller="PlaceCtrl">
<form ng-submit="addPlace()">
<div class="row-fluid">
<div class="span2"><label>Name</label></div>
<div class="span8"><input type="text" class="input-xlarge" ng-model="newPlace.name"></div>
</div>
<input type="submit" class="btn" value="Add">
</form>
</div>
place.js.coffee
app = angular.module("test", ["ngResource"])
app.factory "Place", ($resource) ->
$resource("/places/:id", {id: "#id"}, {update: {method: "PUT"}})
app.factory "Phone", ($resource) ->
$resource("/phones/:id", {id: "#id"}, {update: {method: "PUT"}})
#PlaceCtrl = ($scope, Place, Phone) ->
$scope.addPlace = ->
place = Place.save($scope.newPlace)
console.log place
$scope.newPlace = {}
In place.js.coffee I am able to save Place to the DB in the line (place = Place.save($scope.newPlace)). I want the id of place so I can append it to all Phones that are dynamically built (because Phones has a FK of place_id that points to a Place). However if I type in place.id in console, I get an undefined message. place.name will return the place's name, but id won't work. If I look at console.log place, however, I see that the id field is returned and populated.
2) How do I get the id field of the place JSON object? I am almost positive this is possible since Chrome's console returns the id field but place.id won't give me anything.
Thank you in advance for your help. I greatly appreciate it.
I would try something like this:
$scope.addPlace = ->
place = Place.save($scope.newPlace) ->
$scope.newPlaceId = place.id
console.log place
$scope.newPlace = {}

How do i create dynamic properties in Model and use in Controller and View. - MVC

I am looking for a solution which creates dynamic properties to be create in Model.
I want to use them in my View and Controller.
Can any one have idea, how to create it?
I am having scenario in my project where one page will be having options to be lets say Profile2, Profile5 etc.
Profile 2 can have two URLs to be submit from user.
Profile 5 can have five URLs to be submit from user.
and
So on........
Is there any solution or alternative to do this????
He Amit , For your situation "I am having scenario in my project where one page will be having options to be lets say Profile2, Profile5 etc.
Profile 2 can have two URLs to be submit from user.
Profile 5 can have five URLs to be submit from use"
You want to put this url in your properties ok.
SO do one thing create a property like this.
public List<string> urlList {get;set;}
use this in your property andd add url in the list.
you can add n no of urls.
That is exactly what ViewBag is for. Its a dynamic property on Controller and View.
public ActionResult SomeAction()
{
ViewBag.Message = "Hello, world";
}
<p>#ViewBag.Message</p>
This will allow you to send anonymous property values from your Controller to your View. However, if you're looking to post different numbers of values (urls in your example), you should use an IList as your model.
#model IList<string>
#for (int i = 0; i < Model.Count; i++)
{
#Html.EditorFor(model => model[i])
}
Your model should probably store the values in a list. Here is an example explaining how to display and save data for a list property.
How to interact with List<t> in MVC
see this is what i have done as an alternative.
Make all divs and other fields in MODEL and use jQuery to work around.
I guess this is an alternative, but not exactly what i want. Still looking for answer. I post this as this can be helpful to some one in future.
Please check below.
<div>
#for (var i = 0; i < ProfileCount; i++)
{
<label>
URL:</label>
<input type="text" id=#string.Format("URL{0}", i) />
<label>
CheckName:</label>
<input type="text" id=#string.Format("URL{0}CheckName", i) />
<label>
Run Check From:</label>
#Html.DropDownList(string.Format("URL{0}Region", i), (IEnumerable<SelectListItem>)ViewBag.Regions)
<br />
<span id=#string.Format("URL{0}Result", i)></span>
<input type="button" value="Create check" id=#string.Format("URL{0}CheckSetup", i) onclick="getResponseFromUrl('#string.Format("URL{0}')", i);" />
<input type="button" value="Delete check" id=#string.Format("URL{0}Delete", i) onclick="DeleteCheck('#string.Format("URL{0}')", i);"
style="display: none" />
<input type="hidden" id=#string.Format("URL{0}Hidden", i) />
<br />
<br />
<br />
}
</div>

MVC partial views (or editor templates): append index to input name for multiple use of form?

How can I add an index, to input names and ids in forms that are used multiple times in one view?
I have created a form for photo rotator that provides the ability to edit a context-specific caption for each photo (billboard). I need to be able to include multiple instances of the form fields for this so the admins can edit all of the captions for a rotator's set of photos in one view, and so I need a way to keep ids and field names unique.
Editor templates automatically add a prefix, but when I loop over the photos like this:
<% foreach (var billboard in Model.Billboards ) { %>
<%: Html.EditorFor(x => billboard, "BillboardForm")%>
<% } %>
It simply adds "billboard_" as the prefix, which doesn't solve my problem.
I'd like to append the rotator id billboard id to the end of each input name and id:
<form action="/Rotators/Edit/5" method="post">
<input id="billboard_21_RotatorId" name="billboard_21_RotatorId" type="hidden" value="5" />
<input id="billboard_21_ImageId" name="billboard_21_ImageId" type="hidden" value="19" />
<label for="billboard_21_Title">Title</label>
<textarea cols="20" id="billboard_21_Title" name="billboard_21_Title" rows="2">Title</textarea>
<label for="billboard_21_Caption">Caption</label>
<textarea cols="20" id="billboard_21_Caption" name="billboard_21_Caption" rows="2">This is the caption</textarea>
<select id="billboard_21_TopicId" name="billboard_21_TopicId">
<option value="1">1st option</option>
</select>
</form>
Any easy way to do this??
plz download this sampel code from steve sanderson's blog post. it does not directly relate to your question. But in demo project you will find BeginCollectionItem html helper that is changing the prefix scope for input or series of inputs. This can give u a starting point
Edit:
in ur editor template u can use following method from steve's code like
using(Html.BeginHtmlFieldPrefixScope("BillBoard" + Model.ID.ToString())){
<label>Image<label>
#Html.TextBoxFor(x=>x.Image)
<label>Caption</label>
#Html.TextBoxFor(x=>x.Caption)
}
if ID is property of your model and has value e.g 4 then u will have html like
<label>Image</label>
<input name = "BillBoard4.Image" .../>
<label>Caption</label>
<input name = "BillBoard4.Caption" .../>
Note: The features used below may not have existed 4 years ago...
Firstly, you don't have to use beestings any more, the # syntax used
in the Razor examples is far cleaner.
The method you're calling is in System.Web.Mvc.Html.EditorExtensions:
public static MvcHtmlString EditorFor<TModel, TValue>(
this HtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression
)
...
Your approach:
#foreach (var billboard in Model.Billboards ) {
#Html.EditorFor(x => billboard, "BillboardForm")
}
The body of expression x => billboard is a ConstantExpression.
This approach results in the appropriate scope applying in the EditorTemplate:
#for (var i = 0; i < Model.BillBoards.Count(); i++)
{
#Html.EditorFor(x => Model.BillBoards[i], "BillboardForm")
}
If Model.BillBoards is an array, the expression x => Model.BillBoards[i] can be described as
SimpleBinaryExpression{NodeType:ArrayIndex}(
Left: ConstantExpression,
Right: ConstantExpression
)
If Model.BillBoards is an IList<T>, the expression x => Model.BillBoards[i] can be described as
InstanceMethodCallExpressionN(
Method:RuntimeMethodInfo(IList<T>.get_Item (Int32 index)),
Object:PropertyExpression(ConstantExpression),
Arguments:[ConstantExpression]
)
The overloads of EditorFor() that accept Expressions check the expression body's Type and NodeType and construct the scope accordingly.
This code should be equivalent if you don't have anything else inside the loop:
#Html.EditorFor(x => Model.BillBoards, "BillboardForm")
If you only have a read-only view and an editing view, you can rename your templates and remove the second parameter. Assuming BillBoard is your Model class, rename BillboardForm.cshtml to EditorTemplates/BillBoard.cshtml, then change the code to
#Html.EditorFor(x => Model.BillBoards)

Rebinding a list of textboxes in ASP MVC2 VS2010 Beta2 after postback

So.. I have a problem. I'm sure almost anybody that tried MVC has had it. Nevertheless I've been unsuccessfull in googling a solution or thinking of one for my self.
The problem is this: I have a list of textboxes that I'd like to edit all at once, and I'd also like to add new items to my list. However, the text binding fails after the first postback.
So I've made a small example to illustrate the problem:
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Fields</legend>
<% foreach(string s in Model) { %>
<p>
<%= Html.TextBox("list",s) %>
</p>
<% } %>
<p>
<%= Html.TextBox("newstr") %>
</p>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
The controller code:
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Edit()
{
return View(new List<string>() { "aa", "bb", "cc" });
}
// Remove empty strings and add the new one
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(List<string> list, string newstr)
{
List<string> res = list.Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
if (!string.IsNullOrWhiteSpace(newstr))
res.Add(newstr);
return View(res);
}
So, on first GET i return the 3 strings aa, bb and cc, and get 3 textboxes with their text in, as well as en empty textbox for new strings, like this:
aa
bb
cc
Empty.
Now, if I clear the bb string and add "dd" in the empty textbox, I get a return list of "aa","","cc", and "dd" in newstr. This returns a new list of "aa", "cc", "dd" which is what I would expect to see in my checkboxes. Instead I get:
aa
aa
aa
dd (expected empty)
So.. There is something fundamental I didn't get :) Why does it ignore my new datamodel and use some of the old and not all?
I suppose its some kind of viewstate leftover from asp.net, so how do I turn it off? I really want the stateless webpage as advertised.
If you look at your html source you will see that this has nothing to do with viewstate. When filling inputs after a post the framework will first search the posted values and fill your inputs based on that. Thats why you will get "dd" in your last input. The reason why you get "aa" in the rest of the inputs is that they all have the same name. Your post will look something like this:
list = "aa", list = "", list = "cc"
So when you render a input with the name "list" the framework will search that post and take the first value that matches. This will be "aa" every time. Thats why you get "aa" in all your inputs. You should not have multiple <input type="text" /> with the same name. With unique names you will fix the issue with the looped inputs.
I'm not sure if there is a way to make a <%=Html.TextBox()%> not look in the posted data. But you can always change it to a regular <input type="text" name="newstr" /> and that will work.
Interesting problem. There seems to be a problem inside Html.TextBox(). I debugged your code, and as you can see, the Model in the View does contain the correct List. (BTW, I tested this in Visual Studio 2008).
When you convert the
<%=Html.TextBox("list", s) %>
to a standard
<input id="list" name="list" value="<%=s %>" />
it works like it should work. Is this an option?

Resources