Here is clear exampel about forms:
<div ng-form="namesForm_{{$index}}" ng-repeat="name in names">
<input type="text"
name="input_{{$index}}_0"></input>
<!-- ... -->
Ok, but how I should access $valid field from form? E.g this does not work:
{{namesForm_$index.$valid}}
Even {{namesForm_$index}} outputs 0.
It is need to "inline" $index before {{}} resolve a variable name. How to do that?
It's not easy to get it inside of single {{ }} expression, but if you only want to use it in directives accepting expressions without handlebar (like ng-disabled), you can achieve that:
<div ng-app>
<ng-form name="namesForm_{{$index}}" ng-repeat="name in [1, 2]">
<input type="text"
placeholder="{{$index}}"
ng-required="true"
ng-model="test"
name="hey" />
<button ng-disabled="!namesForm_{{$index}}.$valid">
send
</button>
<br />
</ng-form>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
{{ IsFormValid($index) }}
$scope.IsFormValid = function(index) {
var form = angular.element("formName" + index);
return form.$valid;
};
UPDATED
Working example:
{{ IsFormValid($index) }}
$scope.IsFormValid = function(index) {
var form = angular.element(document.getElementById('#bucketForm-' + index);
return form.$valid;
};
New Approach
The below is an example for dynamic ngModel, same can be replicated for form name :
$scope.formData = {};
$scope.formData = {
settings:
{
apiEndpoint: '',
method: 'get'
},
parameters: {}
};
<div class="form-group" ng-repeat="parameter in apiParameters">
<label for="{{parameter.paramName}}" class="col-sm-2 control-label">{{parameter.paramTitle}}</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="{{parameter.paramName}}" id="{{parameter.paramName}}" ng-model="formData.parameters[parameter.paramName]" placeholder="{{parameter.paramTitle}}">
</div>
</div>
Related
I am new to Angular JS, I created a div with input elements and I didn't use ng-model for input boxes.
<div class="row">
<br>
<div class="col-sm-10" id="rankingForm" >
<p ng-repeat=" x in $ctrl.outputProductAttributeValueList">
{{x}} <input type="text" />
</p>
<br>
<button type="submit" ng-click="$ctrl.onRankingFormSubmit()"> SUBMIT</button>
</div>
</div>
When I click on submit button I have to access all input values .Please help me how to do that .. I tried as below.
angular.module("productList")
.component("productList",{
templateUrl : "product-list/product-list.template.html",
controller : ["$http" ,"$scope","$document",function productListController($http,$scope,$document){
var self = this;
self.outputProductAttributeValueList =[ "age", "gender","all"];
self.onRankingFormSubmit = function () {
var queryResult = $document[0].getElementById("rankingForm")
console.log(queryResult);
// HERE queryResult is printing how to proceed further
};
}]
});
Now I want to collect all those input values dynamically created by ng-repeat. Please tell me how to do that ?
AngularJS ngModel is the standard approach for binding the view into the model instead of interacting directly with the DOM.
You can get all the inputs within the div id="rankingForm" you can do:
var inputs = $document[0]
.getElementById('rankingForm')
.getElementsByTagName('input');
Or by using Document.querySelectorAll():
var inputs = $document[0].querySelectorAll('#rankingForm input');
Once you have the inputs than iterate over all of them to get the values.. Notice that I have added attribute name to the inputs:
Code whitout ngModel:
angular
.module('App', [])
.controller('AppController', ['$scope', '$document', function ($scope, $document) {
$scope.outputProductAttributeValueList = ['age', 'gender', 'all'];
$scope.onRankingFormSubmit = function () {
var inputs = $document[0].querySelectorAll('#rankingForm input');
inputs.forEach(function(input) {
console.log(input.name + ': ' + input.value);
});
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.min.js"></script>
<div ng-app="App" ng-controller="AppController" class="row">
<br>
<div class="col-sm-10" id="rankingForm" >
<p ng-repeat="x in outputProductAttributeValueList">
{{x}} <input type="text" name="{{x}}" />
</p>
<br>
<button type="submit" ng-click="onRankingFormSubmit()">SUBMIT</button>
</div>
</div>
Code with ngModel:
angular
.module('App', [])
.controller('AppController', ['$scope', '$document', function ($scope, $document) {
$scope.outputProductAttributeValueList = ['age', 'gender', 'all'];
// Model inputs
$scope.inputs = {};
$scope.onRankingFormSubmit = function () {
$scope.outputProductAttributeValueList.forEach(function(input) {
// Access to model inputs: $scope.inputs[input]
console.log(input + ': ' + $scope.inputs[input]);
});
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.min.js"></script>
<div ng-app="App" ng-controller="AppController" class="row">
<br>
<div class="col-sm-10" id="rankingForm" >
<p ng-repeat="x in outputProductAttributeValueList">
{{x}} <input type="text" ng-model="inputs[x]" />
</p>
<br>
<button type="submit" ng-click="onRankingFormSubmit()">SUBMIT</button>
</div>
</div>
I seem to be overlooking something simple here but it has me stumped.
Why does nothing happen when i hit the submit button?
<section ng-controller="SavingsController as savingsCTRL">
<form name="createSavingForm" class="form-horizontal" novalidate>
<fieldset>
<!-- Title Box Start-->
<div class="form-group new-deal-form" show-errors>
<label for="title">Title</label>
<input name="title" type="text" ng-model="savingsCTRL.title" id="title" class="form-control" placeholder="Title" required>
<div class="sub-label">Enter the Title of the Deal.</div>
<div ng-messages="savingForm.savingsCTRL.title.$error" role="alert">
<p class="help-block error-text" ng-message="required">Saving title is required.</p>
</div>
</div>
<!-- Title Box End-->
<!--Submit Button Start-->
<div class="form-group buttons-cancel-submit">
<button class="btn btn-default " ng-click="savingsCTRL.cancel()">Cancel</button>
<input type="submit" class="btn btn-success " ng-click="savingsCTRL.create(); submitForm(createSavingForm.$valid)" >
</div>
</fieldset>
</form>
</div>
</div>
</section>
for simplicity i took most of the forms out but what else is wrong?
Savings Controller Function
// Create new Saving
$scope.create = function () {
$scope.error = null;
alert("create");
// Create new Saving object
var saving = new Savings({
title: this.title,
details: this.details,
retailer: this.retailer,
price: this.price,
link: this.link,
image: $scope.user.imageURL,
urlimage: this.urlimage,
tags: this.tags
//startdate: this.startdate,
//enddate: this.enddate
});
// Redirect after save
saving.$save(function (response) {
$location.path('savings/' + response._id);
// Clear form fields
$scope.title = '';
$scope.details = '';
$scope.retailer = '';
$scope.price = '';
$scope.link = '';
$scope.image = '';
$scope.urlimage = '';
$scope.tags = '';
}, function (errorResponse) {
$scope.error = errorResponse.data.message;
});
};
Main issue is, you are mixing controller as syntax with $scope.
According to documentation, we should use this instead of $scope.
... binds methods and properties directly onto the controller using this: ng-controller = "SettingsController1 as settings"
Than, submitForm is not a predefined method, it should be defined in controller first
this.submitForm = function(isValid){
console.log('Submitting form: ' + isValid)
}
In addition to that, bind that to form with ng-submit= "savingsCTRL.submitForm(createSavingForm.$valid)"
See Plunker, with working code. (I took ng-click="savingsCTRL.create()", since we don't have all parts of your application)
Bind the form submit event to ng-submit.
Example: ng-submit="submitForm(createSavingForm.$valid)"
So I am having a little problem creating a very simple query form due to my lack of understanding about coding. As you can see in the app.js below, I have FormController, which retrieves information from the form, feeds it into the jsonUrlGen function which creates a custom URL, which is then sent to my SolrController which accesses that URL and pulls the JSON information from it.
However it is quite clear after taking a step back and looking at it that the structure of my code is wrong, and I am missing an app.service to link the shared variables between my two controllers. I'm also not even sure if I need two controllers in this instance, but it just happened as I was coding it.
If anybody can tell me what I'm doing wrong here I would really appreciate it, because the code just flat out does not work.
Thanks.
.HTML FILE
<html ng-app="solrApp">
<head>
<link link rel="stylesheet" href="bootstrap-3.3.5-dist/css/bootstrap.min.css" />
<link link rel="stylesheet" href="style.css" />
<script src="https://code.angularjs.org/1.4.3/angular.min.js"></script>
<script type= "text/javascript" src="app.js"></script>
</head>
<body>
<!--<h1 class="headline">Logo or Something Here</h1>-->
<div class="logo"><img src="images/CubedE.png" id="cubedE"/></div>
<div class = "queryForm" ng-controller="FormController">
<input type="text" class="queryBox" id="mainQueryString" placeholder="Query String" ng-model="fullQuery.queryString"><br />
<input type="text" class="queryBox" placeholder="Filter Query" ng-model="fullQuery.filterQuery"><br />
<input type="text" class="queryBox" placeholder="Sort By" ng-model="fullQuery.sortBy"><br />
<h2>Extract only from rows:</h2>
<input type="text" class="halfQueryBox" placeholder="Start" ng-model="fullQuery.startRow"><input type="text" class="halfQueryBox" placeholder="End" ng-model="fullQuery.endRow"><br />
<input type="text" class="queryBox" placeholder="Field List (Separate by comma)" ng-model="fullQuery.fieldList"><br />
<input type="text" class="queryBox" placeholder="Raw Query Parameters (key1=val1&key2=val2)" ng-model="fullQuery.rawQuery"><br />
<button type="button" ng-click="jsonUrlGen()">Submit Query</button>
</div>
<div class = "results" ng-controller="SolrController">
<ul>
<li ng-repeat="item in items">
{{ item.key }} - <em>{{ item.value }}</em>
</li>
</ul>
</div>
</body>
</html>
APP.JS
(function(){
var app = angular.module('solrApp', []);
app.controller('FormController', function($scope) {
$scope.fullQuery = {
queryString: '',
filterQuery: '',
sortBy: '',
startRow: '',
endRow: '',
fieldList: '',
rawQuery: ''
}
$scope.jsonUrlGen = function(){
var jsonURL = "http://localhost:8983/solr/core/select?";
if($scope.fullQuery.queryString !== '') {
jsonURL = jsonURL + "q=" + $scope.fullQuery.queryString;
}
else if($scope.fullQuery.filterQuery !== '') {
jsonURL = jsonURL + "&fq=" + $scope.fullQuery.filterQuery;
}
else if($scope.fullQuery.sortBy !== '') {
jsonURL = jsonURL + "&sort=" + $scope.fullQuery.sortBy;
}
else if($scope.fullQuery.startRow !== '') {
jsonURL = jsonURL + "&start=" + $scope.fullQuery.startRow;
}
else if($scope.fullQuery.endRow !== '') {
jsonURL = jsonURL + "&rows=" + $scope.fullQuery.endRow;
}
else if($scope.fullQuery.fieldList !== '') {
jsonURL = jsonURL + "&fl=" + $scope.fullQuery.fieldList;
}
else {
return "exception thrown";
}
jsonURL = jsonURL + "wt=json";
return jsonURL;
};
});
app.controller('SolrController', function($scope, $http){
$http.get($scope.jsonUrlGen)
.then(function(res){
$scope.items = res.data;
});
});
})();
Answers may be opinionated since there are multiple ways to accomplish this.
I would advise to restructure html. Have a single controller that wraps the "form" and the contents of SolrController. Also the "form" should really become a <form>. In angular there is a default controller created for this tag and it helps a lot with managing validation and handling submit.
<div class="results" ng-controller="SolrController">
<form class="queryForm" name="queryForm" ng-submit="submit()">
<input type="text" class="queryBox" id="mainQueryString" placeholder="Query String" ng-model="fullQuery.queryString"><br />
<input type="text" class="queryBox" placeholder="Filter Query" ng-model="fullQuery.filterQuery"><br />
<input type="text" class="queryBox" placeholder="Sort By" ng-model="fullQuery.sortBy"><br />
<h2>Extract only from rows:</h2>
<input type="text" class="halfQueryBox" placeholder="Start" ng-model="fullQuery.startRow"><input type="text" class="halfQueryBox" placeholder="End" ng-model="fullQuery.endRow"><br />
<input type="text" class="queryBox" placeholder="Field List (Separate by comma)" ng-model="fullQuery.fieldList"><br />
<input type="text" class="queryBox" placeholder="Raw Query Parameters (key1=val1&key2=val2)" ng-model="fullQuery.rawQuery"><br />
<button ng-disabled="queryForm.$invalid">Submit Query</button>
</form>
<ul>
<li ng-repeat="item in items">
{{ item.key }} - <em>{{ item.value }}</em>
</li>
</ul>
</div>
Mind name attribute for the form. It will help to access the form in the scope. Actually when there is a name angular creates $scope.queryForm in parent controller
By default all buttons (and <input type="submit") on form submit on click. But type="button" will prevent it. So remove it
Controller SolrController. It's inappropriate to perform a request before user had a change to input something. $http.get should work on a click handler which we choose to be submit event.
app.controller('SolrController', function($scope, $http){
$scope.fullQuery = {};//ng-model will take care of creating all properties
function jsonUrlGen(){ //same code here
}
$scope.submit = function(){
$http.get(jsonUrlGen())
.then(function(res){
$scope.items = res.data;
});
});
};
})
Hope this helps
this my HTML
<div ng-app="timeTable" ng-controller="addCoursesCtrl">
<button class="btn btn-primary" ng-click="addNewCourse()">Add New Course</button><br/><br/>
<fieldset ng-repeat="choice in choices">
<div class="row">
<div class="col-md-6">
<select class="form-control" ng-model="choice.type" ng-options="s for s in coursetoAdd">
<option value="{{s.shortCut}}">{{s.name}}</option>
</select>
</div>
<div class="col-md-6">
<input type="text" placeholder="Enter Course Name" name="" class="form-control" ng-model="choice.course"/>
</div>
</div>
<br/>
</fieldset>
<button class="btn btn-primary" ng-click="convertAndSend()">Submit</button>
</div>
this the js
var timeTable = angular.module("timeTable",[]);
timeTable.controller("addCoursesCtrl", function ($scope,$http) {
$scope.choices = [{ course: '', type: '' }];
$scope.coursetoAdd ;
$http.get("/Semster/getSuggtedCourses").then(function (response) {
$scope.coursetoAdd = response.data;
});
$scope.addNewCourse = function () {
var newITemNo = $scope.choices.length + 1;
$scope.choices.push({ course: '', type: '' });
};
$scope.convertAndSend = function () {
var asJson = angular.toJson($scope.choices);
console.log(asJson);
$http.post('/Semster/Add', asJson);
};
});
this code bind an object {"course":...,"type":....} every time you click on add course ,and add input field dynamically , my problem is with select control,I'm getting the data from server and use it with ng-optin ,but all it shows it's just [object Object] in select option not the real value.
Assuming that the data returned from getSuggestedCourses is an array of objects, the ng-options selector:
s for s in courseToAdd
will bind s to each object in the array. You need to bind to the fields in the object like this
s.value as s.name for s in courseToAdd
I am pretty new to angular and web development in general and I cannot for the life of me figure out what is wrong with my code. Essentially I'm just trying to add to a table that uses ng-repeat by using $scope.arrayname.push. Let me know if I wasn't clear on something. Here are the relevant files:
My angular file:
var routerApp = angular.module('routerApp', ['ui.router']);
...
routerApp.controller('eventController', function($scope) {
$scope.events = [];
$scope.addEvent = function () {
$scope.events.push ({
name: $scope.eventName,
start: $scope.startDate,
end: $scope.endDate,
location: $scope.locationid
});
// Clear input fields after push
$scope.eventName = "";
$scope.startDate = "";
$scope.endDate = "";
$scope.locationid = "";
};
});
and here is my html file where the input goes:
<div class="jumbotron text-center">
<h2>The Event Page </h2>
</div>
<div class="row">
<div class="col-sm-6" ng-controller="eventController">
<div ui-view="columnOne"></div>
<input value="" type="text" placeholder="Name of Event" ng-model="eventName">
<input value="" type="text" placeholder="Start Date" ng-model="startDate">
<input value="" type="text" placeholder="End Date" ng-model="endDate">
<input value="" type="text" placeholder="Location" ng-model="locationid">
<button ng-click="addEvent()">Add to Event List</button>
</div>
<div class="col-sm-6">
<div ui-view="columnTwo"></div>
</div>
</div>
And the data should be outputed in a table here:
<tbody>
<tr ng-repeat="event in events">
<td>{{ event.name }}</td>
<td>{{ event.start }}</td>
<td>{{ event.end }}</td>
<td>{{ event.location }}</td>
<!---<td>{{ event.link }}</td>--->
</tr>
</tbody>
I am using partial views with routerApp from angular. Here is my plunker: http://plnkr.co/edit/FBoWuEQYhCwtTtNN9Wrk?p=preview
Any help is appreciated!
I had to make a few changes to get this to work. The main issue is that the scope isn't being preserved between your table view and the button press so even though the value is bound (you can console.log(events) and it will output correctly) it doesn't display.
First I named the controller ec and moved it up a level
<div class="jumbotron text-center">
<h2>The Event Page </h2>
</div>
<div class="row" ng-controller="eventController as ec">
<div class="col-sm-6" >
<div ui-view="columnOne"></div>
<input value="" type="text" placeholder="Name of Event" ng-model="eventName">
<input value="" type="text" placeholder="Start Date" ng-model="startDate">
<input value="" type="text" placeholder="End Date" ng-model="endDate">
<input value="" type="text" placeholder="Location" ng-model="locationid">
<button ng-click="ec.addEvent()">Add to Event List</button>
</div>
<div class="col-sm-6">
<div ui-view="columnTwo"></div>
</div>
</div>
Then I changed the controller to point to "this" instead of $scope
routerApp.controller('eventController', function($scope) {
var ec = this;
ec.events = [];
ec.addEvent = function () {
ec.events.push ({
name: $scope.eventName,
start: $scope.startDate,
end: $scope.endDate,
location: $scope.locationid
});
// Clear input fields after push
$scope.eventName = "";
$scope.startDate = "";
$scope.endDate = "";
$scope.locationid = "";
};
});
And finally I changed the ng-repeat to use ec.events
<tr ng-repeat="event in ec.events">
There's probably a better way to do it with services or something like that to share the scope but that's all I could get to work.