Interview form with angularjs (repeat and model) - angularjs

I want to make interview questions form with ng-repeat, where when i click submit, it will send all the data, so i need different ng-model for that.
Here is my code
<form role="form" name="interviewForm">
<div class="pr_setportfolio_content interview_div" ng-show="setinterview == true">
<div class="prterms_name_input" ng-repeat="interview in interview">
<span class="prterms_input_text">
{{interview.question}}
</span>
<textarea class="prterms_inputtextarea_name" ng-model="interview_answer" name="interview_answer" placeholder="Enter answer" msd-elastic auto-resize></textarea>
</div>
</div>
</form>
So, anyone have any idea how to make it?
Thank you

Use same model (for example interview.answer instead of interview_answer) for holding answers and then you can get answer for each question in same model. Just iterate on interview list and each index will hold one question and its answer
<form role="form" name="interviewForm">
<div class="pr_setportfolio_content interview_div" ng-show="setinterview == true">
<div class="prterms_name_input" ng-repeat="interview in interview">
<span class="prterms_input_text">
{{interview.question}}
</span>
<textarea class="prterms_inputtextarea_name" ng-model="interview.answer" name="interview_answer" placeholder="Enter answer" msd-elastic auto-resize></textarea>
</div>
</div>

Try to use
ng-repeat="intview in interview"
<textarea class="prterms_inputtextarea_name" data-ng-model="intview.interview_answer" name="interview_answer" placeholder="Enter answer" msd-elastic auto-resize></textarea>
After submitting this form, just collect the answer interview.interview_answer is not null or undefined.

Related

Why aren't all my data validations not validating as designed?

I am developing this application in Angular 2 that has a form that you can populate and if the form is not populated, it will prompt you with what needs to be populated. It works for Customer Name, but then for the rest, for example, "a list of tools is required" does not go away once populated. Here is the code below under app/proposal/proposal-new.component.html:
<h1>Create a Proposal</h1>
<div>
<form #proposalForm="ngForm">
<div class="form-group">
<label for="customer">Customer Name</label>
<input type="text" id="customer" placeholder="ABC Supply" required name="customer" #customer='ngModel' [(ngModel)]="proposal.customer">
<div [hidden]="customer.valid || customer.pristine">
Customer name is required
</div>
</div>
<div class="form-group">
<label for="portfolio_url">Portfolio URL</label>
<input type="text" id="portfolio_url" placeholder="ABC Supply" required name="portfolio_url" #portfolio_url='ngModel' [(ngModel)]="proposal.portfolio_url">
<div [hidden]="portfolio_url.valid || portfolio_url.pristine">
A Portfolio URL is required
</div>
</div>
<div class="form-group">
<label for="portfolio_url">Tools that you'll use on the project</label>
<input type="text" id="portfolio_url" placeholder="Ruby on Rails, Angular, etc" required name="tools" #portfolio_url='ngModel' [(ngModel)]="proposal.tools ">
<div [hidden]="tools.valid || tools.pristine">
A list of tools is required
</div>
</div>
<div class="form-group">
<label for="estimated_hours">Estimated hours</label>
<input type="number" id="estimated_hours" required name="estimated_hours" #portfolio_url='ngModel' [(ngModel)]="proposal.estimated_hours ">
<div [hidden]="estimated_hours.valid || estimated_hours.pristine">
You need to enter your estimated hours for the project
</div>
</div>
<div class="form-group">
<label for="hourly_rate">Hourly rate</label>
<input type="number" id="hourly_rate" required name="hourly_rate" #portfolio_url='ngModel' [(ngModel)]="proposal.hourly_rate ">
<div [hidden]="hourly_rate.valid || hourly_rate.pristine">
You need to enter your hourly rate for the project
</div>
</div>
<div class="form-group">
<label for="weeks_to_complete">Weeks to Complete</label>
<input type="number" id="weeks_to_complete" required name="weeks_to_complete" #weeks_to_complete='ngModel' [(ngModel)]="proposal.weeks_to_complete ">
<div [hidden]="weeks_to_complete.valid || weeks_to_complete.pristine">
You need to enter the weeks you estimate to complete the project
</div>
</div>
<div class="form-group">
<label for="weeks_to_complete">Client Email <em>(Optional)</em></label>
<input type="email" id="weeks_to_complete" name="weeks_to_complete" #client_email='ngModel' [(ngModel)]="proposal.client_email">
</div>
</form>
<div>
<p>Hi {{proposal.customer}},</p>
<p>It was a pleasure getting to meet with you and review your project requirements, I believe it is a great fit for the types of applications that I build out. Please feel free to check out some of my past projects here.</p>
<p>To successfully build out the application I will be utilizing {{proposal.tools}}, and a number of other tools to ensure that the project follows industry wide best practices.</p>
<p>Ensuring that you are fully informed is one of my top priorities, so in addition to incorporating everything we discussed, I will also be creating a project management dashboard and sending you a project update message daily so that you can have a transparent view of the development as it takes place.</p>
<p>To accomplish the project and meet the requirements that we discussed, I am estimating that it will take {{proposal.estimated_hours}} hours in development time to complete. The project should take {{proposal.weeks_to_complete}} weeks to complete and with my hourly rate of {{proposal.hourly_rate}}/hour, the estimated total will be {{proposal.hourly_rate * proposal.estimated_hours}}.</p>
<p>The next step from here is to set up a meeting to finalize the project and sign contracts.</p>
<p>I am excited to working with you and build out this project.</p>
</div>
Here is the app/proposal/proposal.ts:
export class Proposal {
constructor(
public id?: number,
public customer?: string,
public portfolio_url: string = 'http://',
public tools?: string,
public estimated_hours?: number,
public hourly_rate?: number,
public weeks_to_complete?: number,
public client_email?: string,
) {}
}
If there is any other files I should be looking at and posting, please let me know. I am stumped here.
The issue you are seeing is that the local variable portfolio_url is being defined multiple times instead of a new local variable for each input. If you update the local variable definitions, which look like this: #[var_name]='ngModel', to have a unique name for each the validation should work as expected.
Update your HTML to the following:
<h1>Create a Proposal</h1>
<div>
<form #proposalForm="ngForm">
<div class="form-group">
<label for="customer">Customer Name</label>
<input type="text"
id="customer"
placeholder="ABC Supply"
required name="customer"
#customer='ngModel'
[(ngModel)]="proposal.customer">
<div [hidden]="customer.valid || customer.pristine">
Customer name is required
</div>
</div>
<div class="form-group">
<label for="portfolio_url">Portfolio URL</label>
<input type="text"
id="portfolio_url"
placeholder="ABC Supply"
required
name="portfolio_url"
#portfolio_url='ngModel'
[(ngModel)]="proposal.portfolio_url">
<div [hidden]="portfolio_url.valid || portfolio_url.pristine">
A Portfolio URL is required
</div>
</div>
<div class="form-group">
<label for="portfolio_url">Tools that you'll use on the project</label>
<input type="text"
id="tools"
placeholder="Ruby on Rails, Angular, etc"
required
name="tools"
#tools='ngModel'
[(ngModel)]="proposal.tools ">
<div [hidden]="tools.valid || tools.pristine">
A list of tools is required
</div>
</div>
<div class="form-group">
<label for="estimated_hours">Estimated hours</label>
<input type="number"
id="estimated_hours"
required
name="estimated_hours"
#estimated_hours='ngModel'
[(ngModel)]="proposal.estimated_hours ">
<div [hidden]="estimated_hours.valid || estimated_hours.pristine">
You need to enter your estimated hours for the project
</div>
</div>
<div class="form-group">
<label for="hourly_rate">Hourly rate</label>
<input type="number"
id="hourly_rate"
required
name="hourly_rate"
#hourly_rate='ngModel'
[(ngModel)]="proposal.hourly_rate ">
<div [hidden]="hourly_rate.valid || hourly_rate.pristine">
You need to enter your hourly rate for the project
</div>
</div>
<div class="form-group">
<label for="weeks_to_complete">Weeks to Complete</label>
<input type="number"
id="weeks_to_complete"
required
name="weeks_to_complete"
#weeks_to_complete='ngModel'
[(ngModel)]="proposal.weeks_to_complete ">
<div [hidden]="weeks_to_complete.valid || weeks_to_complete.pristine">
You need to enter the weeks you estimate to complete the project
</div>
</div>
<div class="form-group">
<label for="weeks_to_complete">Client Email <em>(Optional)</em></label>
<input type="email"
id="weeks_to_complete"
name="weeks_to_complete"
#client_email='ngModel'
[(ngModel)]="proposal.client_email">
</div>
</form>
<div>
<p>Hi {{proposal.customer}},</p>
<p>It was a pleasure getting to meet with you and review your project requirements, I believe it is a great fit for the types of applications that I build out. Please feel free to check out some of my past projects here.</p>
<p>To successfully build out the application I will be utilizing {{proposal.tools}}, and a number of other tools to ensure that the project follows industry wide best practices.</p>
<p>Ensuring that you are fully informed is one of my top priorities, so in addition to incorporating everything we discussed, I will also be creating a project management dashboard and sending you a project update message daily so that you can have a transparent view of the development as it takes place.</p>
<p>To accomplish the project and meet the requirements that we discussed, I am estimating that it will take {{proposal.estimated_hours}} hours in development time to complete. The project should take {{proposal.weeks_to_complete}} weeks to complete and with my hourly rate of {{proposal.hourly_rate}}/hour, the estimated total will be {{proposal.hourly_rate * proposal.estimated_hours}}.</p>
<p>The next step from here is to set up a meeting to finalize the project and sign contracts.</p>
<p>I am excited to working with you and build out this project.</p>
</div>
Working Plunkr
You shouldn't need to do this:
#portfolio_url='ngModel' [(ngModel)]="proposal.portfolio_url"
In the Angular 2 docs they say:
The hash (#) prefix to "phone" means that we're defining a phone variable
So in your case you are defining portfolio_url multiple times in your code. You do not need to use the hash prefix because the portfolio_url is already defined in your proposal object.
The following should work (read more about the template binding syntax):
<input type="number" id="hourly_rate" required name="hourly_rate" [(value)]="proposal.hourly_rate">
Or you can do this:
<input type="number" id="hourly_rate" required name="hourly_rate" #proposal.hourly_rate>
The angular 2 docs also have another example of user input: https://angular.io/docs/ts/latest/guide/user-input.html

ng-models name collision inside ng-repeat

http://plnkr.co/edit/2UFfaG?p=preview
I used this sample code to build a simple app and I noticed that the edit function doesn't work when you are using ng-models that are repeated in a loop. I know this, because I tried using ng-models outside of the ng-repeat loop and it worked perfectly. So when you have two instances of ng-models with the same name, you get a blank data back when you try to get the values back from the view.
This is my view:
<ul ng-repeat="notes in notes">
<li>
<span ng-hide="editing" ng-click="editing = true">{{note.name}} | {{note.content}}</span>
<form ng-show="editing" ng-submit="editing = false">
<label>Name:</label>
<input type="text" ng-model="name" placeholder="Name" ng-required/>
<label>Content:</label>
<input type="date" ng-model="content" placeholder="Content" ng-required/>
<br/>
<button class="btn" ng-click="edit(note.id)">Save</button>
</form>
</li>
</ul>
This is my edit method:
$scope.edit = function (id) {
var note = notesRef.child(id);
var newNote= {
name : $scope.name,
content : $scope.content
}
};
note.update(newNote);
};
When I refer to a ng-model inside of ng-repeat, I can only get the value null for some reason. I get the correct value when I refer to ng-models outside of the ng-repeat for some reason.
How do we solve this problem? What's the simplest solution?
The problem is that the item belongs to the scope of the repeat.
If you changed your ng-model to:
<ul ng-repeat="notes in notes">
<li>
<span ng-hide="editing" ng-click="editing = true">{{note.name}} | {{note.content}}</span>
<form ng-show="editing" ng-submit="editing = false">
<label>Name:</label>
<input type="text" ng-model="note.name" placeholder="Name" ng-required/>
<label>Content:</label>
<input type="date" ng-model="note.content" placeholder="Content" ng-required/>
<br/>
<button class="btn" ng-click="edit(note)">Save</button>
</form>
</li>
</ul>
Where it's now note.name / note.content.
Then instead of padding the note.id to the edit button, you pass in the entire note i.e ng-click="edit(note)"
Then your controller will get passed the entire note.
$scope.edit = function (note) {
// send note to server via $http, changes to `note` are already made directly to the note itself
};
Hope that makes sense.
it should be like this. As we know ng-repeats directive create their own new scope.
bday.editing
<ul ng-repeat="bday in bdays">
<li>
<span ng-hide="bday.editing" ng-click="bday.editing = true">{{bday.name}} | {{bday.date}}</span>
<form ng-show="bday.editing" ng-submit="bday.editing = false">
<label>Name:</label>
<input type="text" **ng-model="bday.name"** placeholder="Name" ng-required/>
<label>Date:</label>
<input type="date" **ng-model="bday.date"** placeholder="Date" ng-required/>
<br/>
<button class="btn" type="submit">Save</button>
</form>
</li>
</ul>
and here what I understand from your question is that you want to edit only the item on which you have click. this is the solution for the same.
One more solution for the same problem is that create a new function that take one argument that is "bday". make edit true only for this item and set editing false for all others element. this solution is for that case if user doesn't submit the form and click on other item.

Validate field count in angular form

I have a form where a model contains an array of sub-models, like this:
<form name="form1">
<div ng-repeat="sub in model.submodels">
<input ng-model="sub.name" required>
<button ng-click="delSubmodel($index)">x</button>
</div>
<button ng-click="addSubmodel()">+</button>
<button ng-disabled="form1.$invalid" type="submit">Save</button>
</form>
How can I make form invalid when there are no input fields (or, in general, when the count of input fields is less than/greater than some value)
Update: Thanks for responses, I hope this can be done outside of controller.
Okay, I just got what you want to achieve, you will had to add a constraint to the form, which is the size of the subModel, so in your submit method:
Before doing anything
$scope.form1.$setValidity('size', model.subModels.length <= 0);
This will set the validity of the form to false in case your condition is false, or viceversa, you can also show a message to notify it to the user, adding this:
<form name="form1">
<div ng-repeat="sub in model.submodels">
<input ng-model="sub.name" required>
<button ng-click="delSubmodel($index)">x</button>
</div>
<input type="hidden" name="size" ng-model="model.subModels.length" />
<button ng-click="addSubmodel()">+</button>
<button ng-disabled="form1.$invalid" type="submit">Save</button>
You can check this example if you don't feel you didn't understood well my point, which is doing the same, just changing the validity for a single input.
Hope it helps you.

AngularJS - How to make radio group as required fields inside a ng-repeat?

I have an ng-repeat which I am using to repeat my JSON data to create Yes/No radio button group on a set of questions.
My $scope.RadioData has the following JSON data:
{
QuestionCd: "Q1"
QuestionTxt: "Some text for the question 1."
ResponseInd: ""
},
{
QuestionCd: "Q2"
QuestionTxt: "Some text for the question 2."
ResponseInd: ""
},
{
QuestionCd: "Q3"
QuestionTxt: "Some text for the question 3."
ResponseInd: ""
},
{
QuestionCd: "Q4"
QuestionTxt: "Some text for the question 4."
ResponseInd: ""
},
{
QuestionCd: "Q5"
QuestionTxt: "Some text for the question 5."
ResponseInd: ""
}
And my HTML is as follows:
<div ng-repeat="radiodata in RadioData" ng-form="RadioForm">
<div class="form-group">
<label for="QuestionTxt" class="col-md-9 radio-inline">
{{radiodata.QuestionTxt}}
</label>
<div class="col-md-3">
<div ng-class="{ 'has-error' : RadioForm.{{radiodata.QuestionCd}}.$invalid }" class="has-error">
<label class="radio-inline">
<input type="radio" name="{{radiodata.QuestionCd}}"
value="T" ng-model="radiodata.ResponseInd" required/>
Yes
</label>
<label class="radio-inline">
<input type="radio" name="{{radiodata.QuestionCd}}"
value="F" ng-model="QuestionRemarksData.ResponseInd" required/>
No
</label>
<span ng-show="RadioForm.{{radiodata.QuestionCd}}.$invalid" class="help-block">Required Field !</span>
</div>
</div>
</div>
</div>
My rendered HTML looks like this:
Some text for the question 1. o Yes o No
Some text for the question 2. o Yes o No
Some text for the question 3. o Yes o No
Some text for the question 4. o Yes o No
Some text for the question 5. o Yes o No
[Submit Button]
I have added the 'required' attribute to each radio button, but I am not able to make these radio buttons behave as required. If I have radio group outside ng-repeat, the same code makes it required.
So, how to make these set of questions with radio groups required inside ng-repeat?
Did you try using ng-required="true" instead of the html5 required attribute?
<div ng-repeat="radiodata in RadioData" ng-form="RadioForm">
<div class="form-group">
<label for="QuestionTxt" class="col-md-9 radio-inline">
{{radiodata.QuestionTxt}}
</label>
<div class="col-md-3">
<div ng-class="{ 'has-error' : RadioForm.{{radiodata.QuestionCd}}.$invalid }" class="has-error">
<label class="radio-inline">
<input type="radio" name="{{radiodata.QuestionCd}}"
value="T" ng-model="radiodata.ResponseInd" ng-required="true"/>
Yes
</label>
<label class="radio-inline">
<input type="radio" name="{{radiodata.QuestionCd}}"
value="F" ng-model="QuestionRemarksData.ResponseInd" ng-required="true"/>
No
</label>
<span ng-show="RadioForm.{{radiodata.QuestionCd}}.$invalid" class="help-block">Required Field !</span>
</div>
</div>
</div>
</div>
Also, as a note, I seem to remember needing to add an ng-click to each option too, to prevent having to click the radio button twice to clear the error...
Having exactly the same problem, and kind of getting crazy with it, this is what I found (pretty new to angularjs so might be I'm making big mistakes):
After doing some tests found that
<span ng-show="RadioForm.{{radiodata.QuestionCd}}.$invalid"
class="help-block">Required Field !</span>
Is always hiding, tried to log to the console, RadioForm.{{radiodata.QuestionCd}}.$invalid and is telling me
$invalid not available in 'undefined'
So I guess the big problem here is how to ask for the 'component status' in the
radio form, seems they are not recognized simply by the name.
I took a look in JS debugger and a very strange thing appear in the radioForm element
it has a "{{radioData.QuestionCd}}" (written exactly that way) as a property, I
might be missing something important here (clearly don't understand this last thing)
Not of much help, but may be this gives some other clue to someone

Validating nested form in angular

Having this ordinary (name attribute is requred by server) form with angular and can't figured out how to make validations work. What should i put into ng-show="TODO"
http://jsfiddle.net/Xk3VB/7/
<div ng-app>
<form ng-init="variants = [{duration:10, price:100}, {duration:30, price:200}]">
<div ng-repeat="variant in variants" ng-form="variant_form">
<div>
<label>Duration:</label>
<input name="variants[{{$index}}][duration]" ng-model="variant.duration" required />
<span ng-show="TODO">Duration required</span>
</div>
<div>
<label>Price:</label>
<input name="variants[{{$index}}][price]" ng-model="variant.price" />
<span ng-show="TODO">Price required</span>
</div>
</div>
</form>
</div>
ps: this is just piece of form, which is more complicated
Thanks
AngularJS relies on input names to expose validation errors.
Unfortunately, as of today it is not possible (without using a custom directive) to dynamically generate a name of an input. Indeed, checking input docs we can see that the name attribute accepts a string only.
Long story short you should rely on ng-form to validate dynamically created inputs. Something like :
<div ng-repeat="variant in variants" >
<ng-form name="innerForm">
<div>
<label>Duration:</label>
<input name="duration" ng-model="variant.duration" required />
<span ng-show="innerForm.duration.$error.required">Duration required</span>
</div>
<div>
<label>Price:</label>
<input name="price" ng-model="variant.price" required/>
<span ng-show="innerForm.price.$error.required">Price required</span>
</div>
</ng-form>
Working fiddle here
UPDATE : Base on your serverside requirement why not do something like that :
<input type="hidden" name="variants[{{$index}}][duration]" ng-model="variant.duration"/>
<input name="duration" ng-model="variant.duration" required />
The hidden input will be the one read by the server while the other one will be used to do the client side validation (later discarded by server). It s kind of an hack but should work.
PS : Be sure that your form is valid before actually submitting it. Can be done with ng-submit

Resources