Get ng-model with index from ng-repeat in controller - angularjs

I can't find the answer to this over google so i post my question here :
I need to send an http.post request to a php file based on inputs value that I get from a ng-model directive in my view but its located inside a ng-repeat. I must use $index because its from a form that repeat for each line in my database.In simple word it's for update my data base but just the line i'm interested in
But I keep getting the following error
TypeError: Cannot read property '0' of undefined
because my ng-model seems to have another name. Can you explain me how to name a ng-model value in controller with the index so it match the one one the view. Thank's in advance.
Here my code :
<ul>
<li class="err" ng-repeat="error in admin.errors"> {{error}} </li>
</ul>
<ul>
<li class="info" ng-repeat="msg in admin.msgs"> {{msg}} </li>
</ul>
<form class="form-inline" ng-repeat="data in admin.datas track by $index" novalidate ng-submit="admin.modify($index)">
<div class="form-group">
<div class="col-10">
<input class="form-control" type="text" ng-value="data.id" ng-model="admin.id[$index]" id="id">
</div>
</div>
<div class="form-group">
<div class="col-10">
<input class="form-control" type="text" ng-value="data.nom" ng-model="admin.nom[$index]" id="nom">
</div>
</div>
<div class="form-group">
<div class="col-10">
<input class="form-control" type="text" ng-value="data.prenom" ng-model="admin.prenom[$index]" id="prenom">
</div>
</div>
<div class="form-group">
<select class="form-control" id="structure" ng-value="data.structure" ng-model="admin.structure[$index]">
<option value="1">Structure 1</option>
<option value="2">Structure 2</option>
<option value="3">Structure 3</option>
<option value="4">Structure 4</option>
<option value="5">Structure 5</option>
</select>
</div>
<div class="form-group">
<div class="col-10">
<input class="form-control" type="text" id="fonction" ng-value="data.fonction" ng-model="admin.fonction[$index]">
</div>
</div>
<div class="form-group">
<textarea class="form-control" id="message" rows="1" ng-value="data.message" ng-model="admin.message[$index]"></textarea>
</div>
<button type="submit" class="btn btn-primary">Modifier</button>
</form>
my controller :
(function() {
'use strict';
angular
.module('AA')
.controller('adminCtrl', adminCtrl);
function adminCtrl($http){
const admin = this;
/* Parti recup*/
admin.datas = [];
admin.getMsg = function(){
$http.get('/dylan/ActeurAvenir/libs/read.php').then(function(response) {
admin.datas = response.data;
})
}
admin.getMsg();
/* Parti post*/
admin.msgs = [];
admin.errors = [];
admin.modify = function($index){
$http.post('/dylan/ActeurAvenir/libs/modify.php', {
'id' : admin.id[$index],
'nom' : admin.nom[$index],
'prenom' : admin.prenom[$index],
'structure' : admin.structure[$index],
'fonction' : admin.fonction[$index],
'message' : admin.message[$index]
}
).then(function(result) {
if (result.data.msg != '')
{
admin.msgs.push(result.data.msg);
}
else
{
admin.errors.push(result.data.error);
}
})
}
};
adminCtrl.$inject = ['$http'];
})();

Here
$http.post('/dylan/ActeurAvenir/libs/modify.php', {
'id' : admin.id[$index],
'nom' : admin.nom[$index],
'prenom' : admin.prenom[$index],
'structure' : admin.structure[$index],
'fonction' : admin.fonction[$index],
'message' : admin.message[$index]
}
I think you need to access admin.datas[$index].id, admin.datas[$index].nom and so on, since admin.datas is the array
about your ng-model
you should be binding against
ng-model="data.id" which comes from your ng-repeat rather than using admin.datas[$index].id
It is less code, its more declarative, and if you add a filter your code will stop working.

Ok so I find the answer thanks to Gonzalo answer and my own investigation, what You need to do here is to change the http.post() value so it's like
'id' : admin.datas[$index].id, admin.datas[$index].nom and so on
AND change the ng-model in the view so its like :
ng-model="admin.datas[$index].id"
Hope this will help someone in the future.

Related

Doing filter by select value is not working

Not able to add the selected value to the filter in angularjs im getting this error(Error: Unexpected token .)
Inside controller
$scope.search_type_options=[{name:"Name",value:"name"},{name:"Id",value:"id"},{name:"Update By",value:"updated_by"}];
$scope.search_val = function()
{
$scope.fs={$scope.search_type.value:$scope.search_txt};
$scope.filter_dt=$filter('filter')($scope.temp_data,$scope.fs);
}
I need output like
{name:"raj"}
Inside Template
<div class="form-group">
<select name="search_type" ng-model="search_type" ng-options="item as item.name for item in search_type_options">
<option value="">--select search type</option>
</select>
</div>
<div class="form-group">
<input type="text" ng-model="search_txt" class="form-control" placeholder="Search">
</div>
<button type="submit" ng-model="search_btn" ng-click="search_val()"class="btn btn-default">Go</button>
</div>
not sure if this is a correct js syntax
$scope.fs={$scope.search_type.value:$scope.search_txt};
normally it should be written like this
$scope.fs = {};
$scope.fs[$scope.search_type.value] = $scope.search_txt;

Cannot read property '$invalid' of undefined

I am creating a statistics page using angular.
When I submit the form it throws the error Cannot read property '$invalid' of undefined.
Here is the html:
<form name="statsForm" ng-submit="quoteRequestsKpi()" novalidate>
<div class="row">
<div class="col-lg-5">
<div class="form-group" show-errors="{ showSuccess: true }">
<label for="month">Month</label>
<select name="month" id="month" class="form-control" required="required" ng-model="statsIn.month">
<option value="0">January</option>
<option value="1">February</option>
...
</select>
</div>
</div>
<div class="col-lg-5">
<div class="form-group" show-errors="{ showSuccess: true }">
<label for="year">Year</label>
<select name="year" id="year" class="form-control" required="required" ng-model="statsIn.year">
<option value="2016">2016</option>
<option value="2017">2017</option>
</select>
</div>
</div>
<div class="col-lg-2">
<div class="form-group">
<label> </label>
<input type="submit" class="btn btn-primary form-control" value="go" />
</div>
</div>
And here is the js code :
controllers.controller('StatsController', [
'$scope', 'growl', 'appService',
function($scope, growl, appService) {
var logger = log4javascript.getLogger('Stats');
logger.debug('StatsController');
/**
*/
$scope.statsIn = {
month : null,
year : '2017'
};
/**
*/
$scope.$on(EVENT_CURRENT_USER_SUCCESS, function() {
logger.debug(EVENT_CURRENT_USER_SUCCESS);
$scope.init();
});
/**
*/
$scope.quoteRequestsKpi = function() {
logger.debug('quoteRequestsKpi');
$scope.$broadcast('show-errors-check-validity');
if ($scope.statsForm.$invalid) {
return;
}
appService.quoteRequestsKpi($scope.kpiIn).then(function(data) {
if (data.status == SUCCESS) {
$scope.quoteRequestKpis = data.quoteRequestKpis;
} else {
logger.warn('quoteRequestsKpi: ' + JSON.stringify(data));
}
});
}
$scope.ensureUserIsAuthenticated();
}]);
Does anyone know why I am getting an error ?
Because your form is undefined inside your controller. You have to create a reference to the form in your controller.
This could be accomplished either by using controllerAs syntax:
e.g.
In the view:
<div ng-controller="StatsController as vm">
<form name="vm.statsForm">
<!--Input Fields...-->
</form>
</div>
Controller:
var vm = this;
vm.statsForm// This is a reference to your form.
Or if you wish to inject $scope in the controller, then the answer of how to access your form can be found here.
Here's a working plunker.

angularjs dynamic form field undefined scope

Hi I have done this to add dynamic form field
<div ng-repeat="wspVdcMuniTbl in wspVdcMuniTbls">
<div class="col-sm-5">
<label>VDC/Municipalities</label>
<select
ng-model="wspVdcMuniTbl.tbl_vdc_municipality_id[$index]"
options="municipalities"
ng-options="municipality.id as municipality.name for municipality in municipalities">
</select>
</div>
<div class="col-sm-5">
<label>Wards</label>
<input type="text"
ng-model="wspVdcMuniTbl.wards[$index]"
id="Location">
</div>
<div class="col-sm-2">
<label> </label>
<button ng-hide="$first" ng-click="removeServiceArea($index)">-</button>
</div>
</div>
<div class="col-sm-2">
<button ng-click="addServiceArea()">+</button>
and my js part is
$scope.wspVdcMuniTbls = [{}];
$scope.addServiceArea = function(){
$scope.wspVdcMuniTbls.push({});
}
$scope.removeServiceArea = function(index){
$scope.wspVdcMuniTbls.splice(index,1);
}
here adding dynamic form field is working fine but after submit console.log($scope.wspVdcMuniTbl) is undefined what will be the problem please help

Cannot read property '$valid' of undefined

I have a form with a name field and two validations - required and max-length.
When I enter correct value, the form in controller is showing valid and returning true. But on entering wrong data, $valid is not throwing false and simply says -
Cannot read property '$valid' of undefined
Why is the form getting undefined in this case?
Jsfiddle here
Thanks in advance
Add ng-submit attribute to the form:
<form name="myForm" ng-submit="SaveAndNext()" novalidate>
Change controller to:
function myCtrl($scope, $log){
$scope.data = {};
$scope.SaveAndNext = function(){
if($scope.myForm.$valid){
$log.info('Form is valid');
$log.info($scope.data);
} else {
$log.error('Form is not valid');
}
}
}
Remove ng-click event handler from your submit button
Updated fiddle: http://jsfiddle.net/9cgopo7d/1/
I included the $log service because it's a useful default service and you might not know about it.
See demo below pass your form to controller with the submit click
ng-click="SaveAndNext(myForm)"
and now you can easy access all your form properties
function myCtrl($scope) {
$scope.SaveAndNext = function(form) {
console.log(form);
if (form.$valid) {
alert(form.$valid);
} else {
alert("!" + form.$valid)
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="registrationdetails" ng-app="" ng-controller="myCtrl">
<form name="myForm" novalidate>
<div class="list">
<div class="item list-item">
<div class="row row-center">
<div class="col-50"> <span class="form-field-name">Name</span>
</div>
<div class="col-50">
<textarea type="text" rows="5" ng-model="data.Name" name="Name" ng-maxlength=45 required></textarea> <span ng-show="myForm.Name.$dirty && myForm.Name.$invalid">
<span class="form-error" ng-show="myForm.Name.$error.required">Name is required</span>
<span class="form-error" ng-show="myForm.Name.$error.maxlength">Name should be max 45 characters</span>
</span>
</div>
</div>
</div>
<div class="item list-item">
<div class="row row-center">
<div class="col-50"> <span class="form-field-name">Type</span>
</div>
<div class="col-50">
<select ng-class="{defaultoption: !data.Type}" ng-model="data.Type" name="Type" required>
<option value="" disabled selected class="defaultoption">Type</option>
<option value="1" class="actualoption">Type 1</option>
<option value="2" class="actualoption">Type 2</option>
</select>
<span ng-show="myForm.Type.$dirty && myForm.Type.$invalid">
<span class="form-error" ng-show="myForm.Type.$error.required">Type is required</span>
</span>
</div>
</div>
</div>
<div class="item list-item">
<div class="row">
<div class="col">
<input type="submit" class="button" ng-click="SaveAndNext(myForm)" value="Next">
</div>
</div>
</div>
</div>
</form>
</div>
Place $scope.data={}; at the top of controller:-)
This is happening becuase you are directly submit the form which doesn't yet initialized the data object and therefore name data.Name is not recognized.
And if you place $scope.data={} in that case we have empty data object initialized.So in second case we have atleast reference of empty object whereas in first case it doesn't have any reference.
Fiddle
HTML:
<form name="form" id='form' novalidate>
<input type="text"required name="Title" ng-model="Title">
<div ng-messages="form.Title.$error">
<div ng-message="required">Field Required</div>
</div>
</form>
JS:
$scope.save= function(){
if (!scope.createMessage.$valid) {
scope.form.$submitted = true;
return;
}
The format for using $valid should be like this. If you don't get again then visit the official site of AngularJs.
I had similar problem, but in my case I was a ng-if creating a child scope that did not have the form defined.
Just changed the ng-if to ng-show and the form stop be undefined.

how to append typeahead dynamically by click?

Am new to angularjs. and am using this link to create typeahead.
It is working fine. but am unable to create this dynamically.
Please refer a solution.
This is my code
$scope.addField = function() {
var html = '<div class="form-group">
<label for="area2">Area 2</label>
<input type="text" name="area2" ng-model="doctor.area2" placeholder="Search Countries" typeahead="c as c.country for c in countries | orderBy:'+"'country'"+' | filter:$viewValue | limitTo:10" typeahead-min-length="1" typeahead-on-select="onSelectPart($item, $model, $label)" typeahead-template-url="customTemplate.html" class="form-control" >
</div>';
var topScope = angular.element(document).scope();
var elem = $compile(html)(topScope);
angular.element(document.getElementById('more_Areas')).append(elem);
};
<div class="form-group" >
<label ><a ng-click='addField()'>Add More Practice Areas</a></label>
</div>
<div id="more_Areas" >
</div>
You could use this, I've used it a couple of times.. and you can also specify a model for each new field you add by changing the ng-model to field.modelName
$scope.fields = [];
$scope.addField = function() {
var topScope = angular.element(document).scope();
var elem = $compile(html)(topScope);
$scope.fields.push({});
};
<div class="form-group" >
<label>
<a ng-click='addField()'>Add More Practice Areas</a>
</label>
</div>
<div id="more_Areas" >
<div ng-repeat="field in fields">
<input name="category" type="text" ng-model="person.category" placeholder="Category" required/> <span class="alert alert-error ng-show="add-bro.input.$error.required">Required</span>
</div>
</div>

Resources