Angular JS: ng-repeat with dynamic ng-model - javascript

I have this working piece of code that is repeated multiple times, hence would be great for a ng-repeat loop.
For example, two instances of my code are the following.
<div>
<input type="text" ng-model="searchParamaters.userName" placeholder="User Name"/>
<i class="fa fa-times" ng-click="resetSearchField(filterParamDisplay[0].param)" ng-show="showParam(filterParamDisplay[0].param)"></i>
</div>
<div>
<input type="text" ng-model="searchParamaters.userEmail" placeholder="User Email"/>
<i class="fa fa-times" ng-click="resetSearchField(filterParamDisplay[1].param)" ng-show="showParam(filterParamDisplay[1].param)"></i>
</div>
This is the filterParamDisplay array in Javascript:
$scope.filterParamDisplay = [
{param: 'userName', displayName: 'User Name'},
{param: 'userEmail', displayName: 'User Email'}
];
I have been trying to do that into a ng-repeat loop, but without success so far.
This is what I have coded atm.
<div ng-repeat="param in filterParamDisplay">
<input type="text" ng-model="searchParams[{{param}}]" placeholder="{{param.displayName}}"/>
<i class="fa fa-times" ng-click="resetSearchField(filterParamDisplay[$index].param)" ng-show="showParam(filterParamDisplay[$index].param)"></i>
</div>
The problems are into the ng-model variable above, and into the $index in the ng-click and ng-show.
Not sure if this can be done at all, any help is much appreciated, thanks!
UPDATE:
Thanks for all the answers, using
<div ng-repeat="p in filterParamDisplay">
...
ng-model="searchParams[p]"
Works great!
Still struggling on the showParam and resetSearchField functions which do not work properly yet using $index. Here is my code.
$scope.searchParams = $state.current.data.defaultSearchParams;
$scope.resetSearchField = function (searchParam) {
$scope.searchParams[searchParam] = '';
};
$scope.showParam = function (param) {
return angular.isDefined($scope.searchParams[param]);
};

As you bind your ng-models to searchParameters.userName and searchParameters.userMail at first example, you must use searchParameters[param.param] for ng-model in ng-repeat. Also like others said, you don't need to use $index, you got your object as param in ng-repeat scope.
<div ng-repeat="param in filterParamDisplay">
<input type="text" ng-model="searchParameters[param.param]" placeholder="{{param.displayName}}"/>
<i class="fa fa-times" ng-click="resetSearchField(param.param)" ng-show="showParam(param.param)"></i>
</div>
Here is working FIDDLE

<div ng-app="dynamicAPP">
<div ng-controller="dynamicController">
<div ng-repeat="param in filterParamDisplay">
<input type="text" ng-model="searchParams[param.param]" placeholder="{{param.displayName}}" /> <i class="fa fa-times" ng-click="resetSearchField(filterParamDisplay[$index].param)" ng-show="showParam(filterParamDisplay[$index].param)"></i>
</div>{{searchParams}}</div>
</div>
Jsfiddler link this one for get a single object like 'username' or 'email'
you want single value in ng-show and ng-click use above one. or other wise use belowed one.
<div ng-app="dynamicAPP">
<div ng-controller="dynamicController">
<div ng-repeat="param in filterParamDisplay">
<input type="text" ng-model="searchParams[param.param]" placeholder="{{param.displayName}}" /> <i class="fa fa-times" ng-click="resetSearchField(.param)" ng-show="showParam(param)"></i>
</div>{{searchParams}}</div>
</div>
Jsfiddler link this one is get whole object based on the control
this will passes the whole set of object list.

You don't need to interpolate angular variables inside ng-* directives.
Try:
HTML:
<div ng-repeat="p in filterParamDisplay">
<input type="text" ng-model="searchParams[p]" placeholder="{{p.displayName}}"/>
<i ng-click="printme(p.param)">click</i>
</div>
Controller:
$scope.filterParamDisplay = [
{param: 'userName', displayName: 'User Name'},
{param: 'userEmail', displayName: 'User Email'}
];
$scope.printme = function(v) {
console.log(v);
};
jsfiddle

As #aarosil said you do not need to use $index.
I wrote a small jsfiddle, I don't know your logic behind showParam so I mocked it.
View :
<div ng-controller="Ctrl">
<div ng-repeat="param in filterParamDisplay">
<input type="text" ng-model="searchParams[param.param]" placeholder="{{param.displayName}}"/>
<i class="fa fa-times" ng-click="resetSearchField(param)" ng-show="showParam(param)"></i>
</div>
</div>
and controller :
$scope.searchParams = {};
$scope.filterParamDisplay = [
{param: 'userName', displayName: 'User Name'},
{param: 'userEmail', displayName: 'User Email'}
];
$scope.resetSearchField = function(param){
$scope.searchParams[param.param] = "";
};
$scope.showParam = function(param){ ... }
http://jsfiddle.net/29bh7dxe/1/

Related

Angular2 FormArray insert does not update view accordingly

So I have a FormArray containing FormGroups with 3 controls.
Visually it looks like a table with 3 inputs on each row. Here is how it looks:
I want when the user presses tab or enter at the last input in the row - a new empty row to be added after it. So I added (keydown)="addRow($event.keyCode, i)" to the last input and created the function:
public addRow(keyCode, index)
{
if (keyCode !== 9 && keyCode !== 13) {
return;
}
let formItems = this.form.get('items') as FormArray;
formItems.insert(
index + 1,
this.formBuilder.group({
'start': ['', Validators.required],
'title': ['', Validators.required],
'category': [''],
})
);
}
Afther the FormGroup is pushed, I can see the controls correctly in the form array, however the view is updated strangely. After for example I press tab on the last input in the first row I get this result:
Last row is removed and I get two empty rows in the after the first. I couldn't find out why. Here is the FormArray after the push, the items are OK there:
Here is the view code:
<div formArrayName="items">
<div *ngFor="let item of form.controls.items.controls; let i=index" [formGroupName]="i" class="row item-index-{{ i }}">
<div class="form-group">
<div class="col-sm-2">
<input type="text" class="form-control" placeholder="Start" autocomplete="off" formControlName="start">
</div>
<div class="col-sm-4">
<input type="text" class="form-control" placeholder="Title" autocomplete="off" formControlName="title">
</div>
<div class="col-sm-4">
<input type="text" class="form-control" placeholder="Category" autocomplete="off" formControlName="category" (keydown)="addRow($event.keyCode, i)">
</div>
<div class="col-sm-2">
<a class="btn btn-icon-only default">
<i class="fa fa-arrow-up"></i>
</a>
<a class="btn btn-icon-only default">
<i class="fa fa-arrow-down"></i>
</a>
<a class="btn btn-icon-only red">
<i class="fa fa-times"></i>
</a>
</div>
</div>
</div>
</div>
Any idea why this happens?
In case someone has this problem but the cause is different, check if you're adding your controls correctly:
let arr = new FormArray([]);
arr.push(....); // Make sure you do this
arr.controls.push(....); // And not this!
I've encountered this issue once earlier when not inserting formgroup at the end of formarray. Seems Angular is having trouble tracking the index in template for some reason, and by using trackBy solved it. So try:
<div *ngFor="let item of form.get('items').controls; let i=index; trackBy:trackByFn"
[formGroupName]="i" class="row item-index-{{ i }}">
and in TS:
trackByFn(index: any, item: any) {
return index;
}

How do I get the value of a text field using AngularJS?

I want to get the value of a text field value using AngularJS when a form is submitted.
The code below always shows "undefined".
html:
<form ng-submit="AdvanceSearchSubmit($event)" name="AdvanceSearch" novalidate>
<p ng-show="!AdvanceSearch.SearchKeyWord.$pristine && AdvanceSearch.SearchKeyWord.$invalid" class="text-danger">Text Cannot Be Empty!</p>
<div ng-hide="AdvanceSearchModel" class="input-group">
<input name="SearchKeyWord" ng-model="SearchKeyWord" id="SearchKeyWord" class="form-control" placeholder="Search in timeline...." type="text" required>
<span class="input-group-btn" ng-click="isAdvanceSearch='false'; SearchPost(0,'true')">
<button ng-disabled="AdvanceSearch.$invalid" type="submit" name="search" id="search-btn" class="btn btn-flat">
<i class="fa fa-search"></i>
</button>
</span>
</div>
</form>
one attempt:
$scope.AdvanceSearchSubmit = function(event)
{
alert(event.target.value);
};
another attempt:
$scope.AdvanceSearchSubmit = function(event)
{
alert(event.SearchKeyWord.value);
};
instead of event pass the SearchKeyWord as a parameter
ng-submit="AdvanceSearchSubmit(SearchKeyWord)"
controller
$scope.AdvanceSearchSubmit = function(keyWord)
{
alert(keyWord);
};
You don't need to pass the event at all to your AdvanceSearchSubmit on submit. You already have your values available inside $scope like ng-model for input field like ng-model="SearchKeyWord"
alert($scope.SearchKeyWord); //access value from `$scope` directly

Stop multiple field filling with v-model?

I'm pretty new to Vue.js and while I've figured most of the problems I'm hitting out, I can't get my head around this one.
I'm displaying a list of posts based on API output, and want to have a comments box for each post. Posting to the API is working fine and it adds it without a problem, but because I'm using the same v-model for each input in the loop any text entered is replicated throughout all other matching inputs due to the binding.
<div class="row" v-if="">
<div class="col-md-11">
<input type="text" class="form-control" value="" title=""
placeholder="Add comments here.." v-model="note.note">
</div>
<div class="col-md-1">
<button type="button" class="btn btn-default" style="margin-left: -1.5rem" v-on:click="addNote(task.id)">Add Comment</button>
</div>
</div>
JS:
addNote: function (id) {
if (this.note.note) {
Vue.http.headers.common['X-CSRF-TOKEN'] = document.querySelector('#token').getAttribute('value');
this.$http.post('api/note/create/' + id, this.note).then(function (response) {
this.fetchTaskList();
});
}
}
Screenshot:
Is there a different directive I should be using? Or is there another way around this?
You can do this by using index in v-for and then binding each box to the notes comment like so:
<!-- use index, so we know where we are in the loop -->
<div v-for="(note, index) in notes">
{{ note.note }}
<!-- Bind to the comment at the given index -->
<input v-model="notes[index].comment" />
</div>
Now you just need to set that up in data:
data: {
notes: [
{note: 'note 1', comment: ''},
{note: 'note 2', comment: ''},
{note: 'note 3', comment: ''}
]
}
Here's the JSFiddle: https://jsfiddle.net/efxzmq9s/

AnjularJS get value of textboxes after button press

I set the values of textboxes via a ajax request in my controller like this :
$http({method: 'GET', url: url}).success(function(data) {
$scope.valzz = data;
$scope.company = $scope.valzz[0].Company;
});
Then in my html :
<label class="item item-input item-stacked-label">
<span class="input-label">Company :</span>
<input type="text" placeholder="Company" value="" ng-model="company">
</label>
<button class="button button-positive" style="margin-top:10px;" ng-click="saveChanges()">
Save Changes
</button>
This correctly puts the company name in the company textbox. But when make a change to that textbox and press the save button, the new value of the textbox isnt showing - it still gets the original. This is the button click in the controller :
$scope.saveChanges=function(){
alert($scope.company);
};
Why is $scope.company not the new value of the textbox? am i doing something wrong? (sorry if basic i am new to angular)
Try removing value=""
HTML:
<label class="item item-input item-stacked-label">
<span class="input-label">Company :</span>
<input type="text" placeholder="Company" ng-model="company">
</label>
<button class="button button-positive" style="margin-top:10px;" ng-click="saveChanges()">
Save Changes
</button>
In corresponding CONTROLLER:
$scope.saveChanges = function() {
alert($scope.company);
};
You don't have a watcher for that model.
$scope.$watch('company', function(company) {
console.log(company);
}
Or in your template, you can interpolate the value:
{{company}}
And then you can see it changing on the html page, because angular make a watcher for it behind the scene
Needed to put this.company not $scope
Please define $scope.company before $http call
app.controller('myCtrl', function($scope, $http){
$scope.company = null; // <--
$http({method: 'GET', url: url}).success(function(data) {
$scope.valzz = data;
$scope.company = $scope.valzz[0].Company;
});
}
Because, once the partials has rendered, it gets only the defined properties in $scope. After that if any property is added inside $scope it needs to call the $apply.
Hope this may help you.
I would assume that you have $scope working properly, and that you have initialized the controller in your app, as well as linked to the proper controller file. Please compare your code to what I have here, as this is working properly.
HTML:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<script src ="controller.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="testController">
<form>
<label class="item item-input item-stacked-label">
<span class="input-label">Company :</span>
<input type="text" placeholder="Company" ng-model="company">
</label>
<button class="button button-positive" style="margin-top:10px;" ng-click="saveChanges()">
Save Changes
</button>
</form>
</div>
</body>
</html>
Controller:
(function(){
'use strict';
var app = angular.module('myApp', []);
app.controller('testController', [ '$scope', function ($scope){
$scope.saveChanges=function(){
alert($scope.company);
};
}]);
})();
Edit: Fiddle

How to implement Ember-Validations in Ember-App-Kit(EAK)

I have a ember-app-kit application. For the form I am using ember default views. But for form validations I have came across with this lib which everyone highly recommends. Ember Validations By Docyard . But I am not sure how to implement the same with my eak set-up.
Questions that I have:
1. Where should I add validations ?
2. What to declare when defining validations?
3. Errors how to show them on focus out or even on submit button ?
Say for example I have a sign up form and I want to validate firstname lastname, email, password, gender(select options) . How should I go about it ?
If possible please clarify the queries with a JSbin.
Validations should go to controller, unless your working with dyanmic formsets, which can be duplicated. Also u have to wrap ControllerObject into this
var AddController = Ember.ArrayController.extend(Ember.Validations.Mixin, {}
To start validation u have to make new Object named validations
You have to add input value to be validated
validations: {
newFirstname:{
format: { with: /^[A-Za-z-]{2,16}$/, allowBlank: true, message: 'Enter valid name.' }
},
newFamilyname: {
format: { with: /^[A-Za-z-]{3,16}$/ , message: 'Required field lastname.' }
}
},
Showing errors.
<div class="row">
<div class="col-md-6 col-xs-4">
<label>First name: </label>
{{input type="text" placeholder="First name" value=newFirstname class="form-control"}}
{{#if errors.newFirstname}}
<span class="error errorForValidation"><span class="glyphicon glyphicon-warning-sign"></span> {{errors.newFirstname}}</span>
{{/if}}
</div>
<div class="col-md-6 col-xs-4">
<label>*Last name: </label>
{{input type="text" placeholder="Family name" value=newFamilyname class="form-control"}}
{{#if errors.newFamilyname}}
<span class="error"><span class="glyphicon glyphicon-warning-sign"></span> {{errors.newFamilyname}}</span>
{{/if}}
</div>
</div><!--end row-->
Showing button when validation is flawless
<button type="submit" class="btn btn-primary" {{bind-attr disabled="isInvalid"}}{{action 'GetData'}}>Create</button>
JSBIN : http://emberjs.jsbin.com/iDeQABo/17/edit

Categories

Resources