I'm trying to apply the autocomplete feature in my angular project, but it does not works.
Here code -
<!-- Start ignoring BootLintBear -->
<form class="navbar-form navbar-left">
<!-- Stop ignoring BootLintBear -->
<div class="input-group" id="nav-group">
<input #input type="text" name="query" class="form-control" id="nav-input" (keyup)="onquery($event)"
[(ngModel)]="searchdata.query">
<div id="output"></div>
<script>
function suggestMe(data) {
document.getElementById('output').innerHTML = data;
}
var storeData = '';
document.getElementById('nav-input').onkeyup = function() {
if(storeData!== ''){
document.body.removeChild(storeData);
}
var textBox = document.getElementById('nav-input').value;
storeData = document.createElement('script');
storeData.src = 'http://en.wikipedia.org/w/api.php?action=opensearch&limit=10&format=json&callback=suggestMe&search=' + textBox;
document.body.appendChild(storeData);
};
</script>
<div class="input-group-btn">
<button class="btn btn-default" id="nav-button" type="submit" (click)="submit()">
<i class="glyphicon glyphicon-search"></i>
</button>
</div>
</div>
</form>
Suggestions are welcomed : )
Instead of mixing pure JavaScript with Typescript, why not do it in full Typescript ? Try this way or adapt it to your need. First set up an observable stream
data: Observable<any>;
private searchTerms = new Subject<string>();
onquery(term: string): void {
this.searchTerms.next(term);
}
Next, set up the search feature
ngOnInit(): void {
this.data = this.searchTerms
.debounceTime(300) // pause in events
.distinctUntilChanged() // ignore if search term not changed
.switchMap(term => term // switch to new observable each time
//http service to retrieve your data
? this.searchService.search(term)
: Observable.of<any>([])
)
.catch(error => {
console.log(error);
});
}
Template :
<input #input type="text" name="query" class="form-control" id="nav-input" (keyup)="onquery(input.value)">
<div id="output">
<div *ngFor="let item of (data | async)">{{ item }}</div>
</div>
Related
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)"
I am currently facing a problem, which has to do with views. I am making an app, which allows for users to create polls. When the poll that a user creates is submitted, I call a POST route to store it:
$scope.userVal = Auth.getCurrentUser();
$http.post('/api/users/update' + $scope.userVal._id, {polls: $scope.polls}).success(function(res){
//console.log("res: ", res);
});
Essentially, I get the user info,and use his id to store the new poll in a schema-defined value called polls.
Now, when a user clicks a button, I display the polls that were created via a ng-view:
$scope.pollView= function(){
$scope.userVal2 = Auth.getCurrentUser();
$scope.userVal2 = $scope.userVal2.polls;
$scope.button = true;
};
In the html, I simply iterate over $scope.userVal2. My problem comes when I try to view a newly created poll. The poll does not initially show up, but if I refresh the page, then it shows up. Is there any reason for this? Does this have to do with the async calls?
Any help would be appreciated!
edit:
Controller:
'use strict';
angular.module('voteApp')
.controller('WallCtrl', function ($scope, $http, Auth) {
$scope.items = [];
$scope.title;
$scope.button = false; //set default to the new poll
$scope.polls = [];
$scope.items.push({id:1, upvotes:0, text:""});
$scope.items.push({id:2, upvotes:0, text:""});
$scope.addOptions = function(){
$scope.items.push({id:$scope.items.length +1, upvotes:0, text:""});
};
$scope.process = function(name, values){
$scope.polls.push({title:name, options:values});
$scope.title = ""; //reset the values for the next poll
$scope.items = [];
$scope.items.push({id:1, upvotes:0, text:""});
$scope.items.push({id:2, upvotes:0, text:""});
$scope.userVal = Auth.getCurrentUser();
$http.post('/api/users/update' + $scope.userVal._id, {polls: $scope.polls}).success(function(res){
//console.log("res: ", res);
});
};
$scope.newView= function(){
$scope.button = false;
};
$scope.pollView= function(){
$scope.userVal2 = Auth.getCurrentUser().polls
$scope.button = true;
};
$scope.delete = function(val){
$scope.polls = $scope.polls.filter(function(returnableObjects){
return returnableObjects.title !== val.title;
});
};
});
html:
<div ng-include="'components/navbar/navbar.html'"></div>
<header class="hero-unit" id="banner">
<div class="container">
<h1>Dashboard</h1>
<p class="lead">What would you like to do today?</p>
<button ng-click="newView()" type="button" class="btn btn-lg newpoll">New Poll</button>
<button ng-click="pollView()"type="button" class="btn btn-lg mypolls">My Polls</button>
</div>
</header>
<div ng-show= "!button">
<form name="form" ng-submit="process(title, items)">
<h2 class="col-md-12 text-center">New Poll</h1>
<h5 class="col-md-12 text-center">Name your poll.</h1>
<input name="pollname" ng-model="title"type="text" class="form-control input_width" placeholder="Poll Name" required>
<br>
<h5 class="col-md-12 text-center">Options</h1>
<div ng-repeat="item in items">
<p>
<input name = "{{item.id}}" ng-model="item.text" type="text" class="form-control input_width" placeholder="Option {{item.id}}" required>
</p>
</div>
<br>
<div class="text-center">
<button type="button"ng-click="addOptions()" class="btn options" formnovalidate>More Options</button>
</div>
<br>
<div class="text-center">
<button type="submit" class="btn button" validate>Submit</button>
</div>
</form>
</div>
<div ng-show="button" >
<br>
<div ng-repeat="poll in userVal2">
<div class="polldeco">
{{poll[0].title}}
<button class="btn buttondeco" ng-click="delete(poll)">Delete</button>
</div>
</div>
</div>
Some ideas:
$scope.userVal2 = Auth.getCurrentUser().polls is using the old version prior to the creation of a new poll? Maybe this could be changed to something like Auth.getCurrentUser().then(...). Either way, ensure that the call to getCurrentUser() is returning new data.
ng-view is cached. When a template is initially requested, it gets stored in the $templateCache. If this template is rendered on the backend for display in as a partial (eg: ng-view) and it is not static content, then you will have to invalidate the cache to update the view.
Consider having the backend return the new poll from $http.post('/api/users/update' ...) and adding it to the list used by ng-repeat. Something like:
$scope.process = function(name, values) {
$scope.polls.push({title:name, options:values});
...
$http.post('/api/users/update' + $scope.userVal._id, {polls: $scope.polls}).success(function(poll){
$scope.polls.push(poll);
});
};
...
<div ng-repeat="poll in polls">
<div class="polldeco">
{{poll[0].title}}
<button class="btn buttondeco" ng-click="delete(poll)">Delete</button>
</div>
</div>
I'm having trouble in wanting to create multiples of the same html that I render in a certain class. For example, I have a div that might look like this
[Header goes here, is a input field] [Dropdown]
[TextArea]
[Submit]
[Add another field]
On add another field, I would like to clone this view and be able to add as many again.
Here's what I have so far:
var UpdateForm = React.createClass({
handleSubmit : function(e) {
e.preventDefault();
var title = React.findDOMNode(this.refs.title).value.trim();
var date = React.findDOMNode(this.refs.date).value.trim();
var body = React.findDOMNode(this.refs.body).value.trim();
if(!title||!date || !body ) {
return;
}
this.props.onSubmit({title:title, date : date, body : body});
React.findDOMNode(this.refs.title).value = '';
React.findDOMNode(this.refs.date).value = '';
React.findDOMNode(this.refs.body).value = '';
//React.findDOMNode(this.refs.sub).value = '';
},
render: function() {
return(
<div id = "This is what I want to duplicate on each button click">
<form className="form-horizontal" onSubmit={this.handleSubmit}>
<div class="form-control">
<label className="col-sm-0 control-label ">Title:</label>
<div class="col-sm-5">
<input className = "form-control" type = "text" placeholder="Title...." ref = "title"/>
</div>
</div>
<div class="form-control">
<label className="col-sm-0 control-label ">Date:</label>
<div class="col-sm-5">
<input className = "form-control" type = "text" placeholder="Date...." ref = "date"/>
</div>
</div>
<div className="form">
<label htmlFor="body" className="col-sm-0 control-label">Report Body:</label>
<div className="column">
<textarea className = "ckeditor" id = "ckedit" ref = "body"></textarea>
</div>
</div>
<div class="form-group">
<label className="col-sm-0 control-label"></label>
<div class="col-sm-5">
<input type = "submit" value="Save Changes" className = "btn btn-primary" />
</div>
</div>
</form>
<div className="btn-group">
<button type="button" className="btn btn-danger">Assign to</button>
<button type="button" className="btn btn-danger dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span className="caret"></span>
<span className="sr-only">Toggle Dropdown</span>
</button>
<ul className="dropdown-menu">
{
this.props.forms.map(function(form){
return (
<li>{form}</li>
)})}
</ul>
<button className="btn btn-success btn-block" onClick={this.addInputField}>Add Subform</button>
</div>
</div>
);
}
});
What I think I need to add:
addDiv: function(e) {
e.preventDefault();
//have a array of divs?
//push a the same div into it?
//then set state of that array?
}
I know in jquery I could just write a function that appends this markup whenever I hit a button, but i don't know how to think about it here at all.
I think what you want is to have a button which add another header-date-body-Component to the form, which should then also be submitted, right?
If so then you need to think more in components. Have one Component which handles the form. Have one around that which handles adding other forms.
<ReportDialog>
<ReportForm>
<ReportForm>
<button onClick={this.addReport}>Add another</button>
</ReportDialog>
To accomplish the multiple ReportForms you need to think about the data in your component, which are reports (I assume). So you need a state in ReportDialog which keeps track of your reports. so at the start of the app you have one report:
getInitialState: function () {
return {
reports: [{ title: '', body: '', date: new Date() }]
};
}
So in addReport you then need to change the state and add another report. To have these reports rendered you already used map, but this time you need to loop over the reports in your component and return a ReportForm for each report.
Hey so I have a form which has three fields name,email and phone.
<div ng-show="Nerd.adding">
<form class="col-sm-6" name="Nerd.nerdAddFrm" novalidate >
<div class="form-group">
<label for="inputName">Name</label>
<input type="text" class="form-control" id="inputName" placeholder="Name" ng-model="Nerd.nerd.name" required >
</div>
<div class="form-group">
<label for="inputEmail">Email</label>
<input type="email" class="form-control" id="inputEmail" placeholder="Email" ng-model="Nerd.nerd.email" required >
</div>
<div class="form-group">
<label for="inputPhone">Phone</label>
<input type="text" class="form-control" id="inputPhone" placeholder="Phone" ng-model="Nerd.nerd.phone" required >
</div>
<button ng-click="Nerd.saveNerd(Nerd.nerd)" type="submit" class="btn btn-primary">Submit</button>
<button ng-click="Nerd.load()" type="button" class="btn btn-default">Cancel</button>
</form>
</div>
As you can see the cancel button calls a Nerd.load() function in the controller. The controller basically resets the view and resets all the binded data to the model.
Nerd.load = function () {
Nerd.editing = false;
Nerd.adding = false;
Nerd.nerd = [];
nerdResource.query(
function (data) {
Nerd.nerds = data;
}
);
};
You can see that I am setting Nerd.nerd equal to an empty array. This should empty out the form fields data. It works fine for Name and Phone. But when I go back to the page it still shows what was last typed. There is no page reload as I am showing and hiding divs based on controller variables. EG <div ng-show="Nerd.adding">. Can anyone help me out with this?
I am on angularjs version 1.3.14. Any help on this would be great.
Thanks.
You need to attach these variables to your $scope like so:
$scope.Nerd.load = function () {
$scope.Nerd.editing = false;
$scope.Nerd.adding = false;
$scope.Nerd.nerd = [];
nerdResource.query(
function (data) {
$scope.Nerd.nerds = data;
}
);
};
Also, I think you should set $scope.Nerd to an empty object like:
$scope.Nerd = {};
instead of setting it to an empty array. You need to use $scope when interacting with the view. This code doesn't look the angular the way it is currently written.
If you can try according some way.
Nerd.load = function () {
Nerd.editing = false;
Nerd.adding = false;
Nerd.nerd = [];
nerdResource.query(
function (data) {
Nerd.nerds = data;
Nerd.nerd = []; // Put here and array make Empty
}
);
};
Can't access form variable from my controller, when i try to access it by $scope.locationForm i've got 'undefined', but when i call console.log($scope) i can see in console there have loactionForm.
My HTML code
<div ng-controller="LocationsController as ctrl">
<form class="form-inline" name="locationForm">
<div class="form-group">
<!-- <div class="input-group"> -->
<label for="location-name">Название населенного пункта</label>
<input required
name="name"
ng-model="ctrl.location.name" type="text" class="form-control" id="location-name" placeholder="Название населенного пункта">
<label for="location-name">Район</label>
<select required
name="region_id"
ng-model="ctrl.location.region_id"
ng-options="region.id as region.name for region in ctrl.regions" class="form-control" placeholder="Название района"></select>
<input ng-click="ctrl.save()"
ng-disabled="locationForm.$invalid" type="submit" class="btn btn-default" value="Cохранить">
<a class="btn btn-default" ng-click="ctrl.reset()" ng-show="locationForm.$dirty">Сброс</a>
<!-- </div> -->
</div>
</form>
My Controller code:
function LocationsController($scope, Location, Region, $q) {
var lc = this,
l_index;
lc.form ={};
lc.regions = lc.locations = [];
lc.regions = Region.query();
lc.regions.$promise.then(function(data) {
lc.locations = Location.query();
});
lc.getRegion = function (id) {
return lc.regions.filter(function(obj) {
return obj.id == id;
})[0].name;
};
console.log($scope);
// console.log($scope.locationForm);
lc.reset = function () {
lc.location = new Location;
}
lc.reset();
};
The problem is when the LocationsController is initialized the form element is not yet compiled. So one possible hack is to use a timeout like
function LocationsController($scope, Location, Region, $q, $timeout) {
//then later
$timeout(function(){lc.reset();})
}