I am trying to write feature in my application whereby i have an input field, and upon the user typing a value, i should post the value (upon every character typed) to a service/method in my backend code... I should then expect a JSON object of matching results. For example:
If i type: wi
I should see the below returned:
willow
wind
wine
window
william
wilter
wistle
will
If i add an n to the value, e.g I should see the below returned:
window
HTML:
<input type="text" ng-model="serachTerm">
<li ng-repeat="data in SearchResults">
{{ data }}
</li>
JS:
This is a service ive used to get data, but unsure on how to send and listen for updates on every character typed:
app.factory('getDataFactory', function($http) {
return {
getData: function(done) {
$http.get('data.json')
.success(function(data) {
done(data);
})
.error(function(error) {
alert('Something has broke');
});
}
}
});
You should take a look at the directive created by the people over at ui bootstrap.
It is an autocomplete directive that handles the data input and sends it to the backend and renders the suggestions.
They even have working code examples for you to see how to wire the different parts up.
Typeahead
Related
Using the Javascript, Vue.js and Typeahead.js way shown by Jeffery Way and Algolia docs to index json objects from the Algolia platform.
Currently when i search for the result i require and hit the submit button, It is passing the name attribute through in the post request.
How is it possible to pass the name and the id attribute or if nescessery just the ID arrtibute would work.
<script>
new Vue({
el: 'body',
data: {
query: '',
users: []
},
ready: function(){
this.client = algoliasearch("MYID", "MYAPI");
this.index = this.client.initIndex('dev_category_list');
$('#typeahead').typeahead(null, {
source: this.index.ttAdapter(),
displayKey: 'name'
});
},
methods: {
search: function(){
if (this.query.length < 3) return;
this.index.search(this.query, function(error, results){
this.users = results.hits;
}.bind(this));
}
}
})
</script>
As a total newcomer the laravel, vuejs and javascript its somewhat difficult to get to grips with the syntax and phrases used when explaining the instructons within the docs so any help would be greatly appreciated.
My indexed objects look like so:
{
"id": "3",
"name": "My Product 3",
"value": "3",
"alternative_name": "Prod 3",
"objectID": "3"
}
Im hoping to pass the value of ID or objectID along with the name attribute in a post request once the user selects the given result from the algolia drop down menu and hits the submit, just the ID would work as mentioned above if its not possible.
Thanks.
--- Update referencing Jerska: ---
Ok so after playing around as a newbie for a little bit i seem to have it working, Im not exactly sure how secure this is or how reliable one would say, Hopefully im not a million miles off from where i need to be. Be good to see what your personal and professional thoughts are.
.on('typeahead:select', function (e, suggestion) {
$('#typeahead').change(function() {
var val = suggestion.id;
$('#st').val(val);
});
I have created a hidden input field and named is 'st' for a demo and on update of the algolia results jquery is using the .change function to append the value to the hidden input fields value. That way the form can be continued and sibmitted as i originally wanted and hoped for, The benefit here is that even if the user is to select a result from algoia drop down menu then continue with the form, If he or she decides they want to go back to the search field and change it, They can do before they submit the form or before any window.location is run, I even thought of using ajax or simply jquery $.post but its working ok the .change
Look forward to hearing your thoughts.
Thanks
If you want to redirect to an item page, the typeahead:select event gives you the selected option :
$('#your-input')
.typeahead(/* ... */)
.on('typeahead:select', function (e, suggestion) {
window.location = suggestion.url;
});
from Algolia redirect to search results
You can access the selected object through the suggestion parameter. You could definitely use something like
window.location = 'YOUR_URL?id=' + suggestion.id + '&name=' + suggestion.name;
This assumes you're using typeahead.js#0.11.
typeahead.js being unmaintained, Algolia recommends to use their own fork of typeahead.js#0.10, autocomplete.js.
Here are the different event names and handlers signatures depending on what library/version you're using:
typeahead.js#0.11: typeahead:select -> function($event, suggestion)
typeahead.js#0.10: typeahead:selected -> function($event, suggestion, datasetName)
autocomplete.js: autocomplete:selected -> function($event, suggestion, datasetName)
I have the following issue with angular and the html select-input:
When the user loads the page my select is empty until the data is loaded and returned from the corresponding service.
In this case the select is populated correctly.
However, the user should be able to filter the model with a click on a button.
When I press the button a new request is send to the REST-API and the response contains the new model for the select.
Unfortunately, the select won't update correctly even when I change it's model
Here is some code to illustrate my problem:
// This happens in my controller
EventService.getAvailableRooms(requestObject).then(function successCallback(response){
// sanatizeRoomTypes is used to generate user-friendly names instead of [1, 2,..]
vm.rooms = DataSanatizer.sanatizeRoomTypes(response.data);
}, function errorCallback(response){
console.log(response)
});
vm.rooms is the model of my select:
<select id="roomSelect" ng-model="eventCtrl.selectedRooms"
ng-options="room.name group by room.type for room in eventCtrl.rooms track by room.id" multiple required>
</select>
In some cases the select duplicates it's model or looses entries. It seems like there is some sort of data binding problem.
Thanks,
Try wrapping your model changes in $scope.apply :
$scope.$apply(function() {
$scope.data.myVar = "Another value";
});
Read here for more info:
http://tutorials.jenkov.com/angularjs/watch-digest-apply.html
You can also use $scope.$watch on the changing $scope variables to update them in your view.
I am able to retrieve following JSON data (test data) from a php file :
JSON:
[{"id":"1","name":"shabri","desc":"bbkbjkbjbjnnklnln","location":"location","mobile":"498534534","telephone":"4549385","offer":"20","email":"nfnkjrnfnrndnrgnkjr"},{"id":"2","name":"bhagatfergdfgfdg","desc":"vfdgfdbgbbgbg","location":"fbgbgfbgfb","mobile":"544656757","telephone":"4223424","offer":"30","email":"vdsxdvgvgv"},{"id":"3","name":"rddfdgdf","desc":"bdffgd","location":"fghgfhfhgf","mobile":"8598","telephone":"856845","offer":"6","email":"httrdh6kiki"}]
Angular Js Controller
.controller('RestaurantsCtrl', ['$scope', '$http', function ($scope, $http) {
$http.get('http://xyz/getRestros.php')
.success(function(data) {
alert(data);
$scope.Restaurants = data;
});
}])
I am sure that JSON data is retrieved because for testing i have alert(data) which displays correct json encoded data in the alert box.
Issue is that data is not getting assigned to $scope.Restaurants. so ng-repeat in html is not populating the list.
ng-repeat populates the list if i hard code $scope.Restaurants.
what's the mistake here ? please help..
EDIT:
hard coded $scope.Restaurants that works:
$scope.Restaurants = [
{ name: 'Shabri', id: 1 },
{ name: 'Bhagat Tarachand', id: 2 },
{ name: 'Udipi', id: 3 },
{ name: 'Shahu', id: 4 },
{ name: 'Bagdadi', id: 5 },
{ name: 'Shiv Sagar', id: 6 }
];
ng-repeat:
<a class="item item-thumbnail-left" ng-repeat="Restaurant in Restaurants | filter: searchText" href="#/app/Restaurants/{{Restaurant.id}}">
<img src="img/default_restro.png" style="margin-top:30px;"/>
<h2 style="font-weight:bold;">{{Restaurant.id}}</h2>
<p>{{Restaurant.name}}</p><br>
<span style="white-space: pre-wrap; font-weight:300;">This is the description about the restaurant click to know more.</span><br>
</a>
You can do debugging in Chrome Developer Tools view (Ctrl-Shift-I) and set breakpoint to see if $scope.Restaurant has value assigned after the line
$scope.Restaurants = data;
You need to parse the returned JSON string into an object.
Try
arrayData = JSON.parse(data);
$scope.Restaurants = arrayData;
It's not actually a answer but i found the root cause of the problem above and might happen with someone.
The free web hosting I was using to host that php file was the culprit.
Everytime that php is executed that web hosting appended some google analytics script at the end after the object ends. That script doesn't appear while live editing that file . i don't know how.
Anyway , i found it when i debugged the $scope.Restaurants again.
It seems that if anything else is echoed with the JSON object thn it would serialize and consider it string.
After correcting and changing the host , difference was spotted and it was considered as actual json objects, and it worked fine.
I have an account form with many inputs. One of them below:
<input class="form-control " placeholder="First Name" type="text" ng-model="account.first_name" ng-init="account.first_name=user.account.first_name">
I have a service in my controller that returns all of the user's information. I'm trying to, in inputs, show the current information on file.
I want this in an input so they can also change (update) it.
However, when I set value="{{user.account.first_name}}" which is returned by my API from my service and set equal to $scope.user, it shows nothing in the input.
I searched for answers on SO and found a few that suggested ng-init, which still didn't work.
I've also tried ng-bind, ng-value, and putting these before I set ng-model.
How can I do this?
Edit:
Here is my account controller. The service just has return $http.get('/api/account');
app.controller('AccountCtrl', function($scope, Account) {
Account.show()
.success(function(data) {
$scope.user = data;
});
data is a JSON schema like so:
{"account": {}, "documents": {}}
But with data inside.
Do that in controller after you get data from your service
Account.show()
.success(function (data) {
$scope.user = data;
//set account.first_name here
$scope.account = {
first_name: $scope.user.account.first_name
};
//or you can use angular.copy(source, destination)
angular.copy(data.account, $scope.account)
});
Why don't you save yourself the headache and drop the account business off the model. I don't see what function it serves, just use the user object. Double alternative:
In your controller:
$scope.account = angular.copy($scope.user);
Ok, first a simplified portion of the Javascript:
//the network values below are later dynamically
//reloaded at runtime from a remote API
$scope.networks = [{id: 5, name: "Network 1"}];
$scope.campaign = {
paths: [
{offers: [
{name: "Site1",
network: $scope.networks[0],
uri: "http://uri1.com"},
{name: "Site2",
network: $scope.networks[0],
uri: "http://uri2.com"}]}]};
And the relevant part of the HTML:
<div ng-repeat "path in campaign.paths">
<div ng-repeat="offer in path.offers">
<input type="text" ng-model="offer.name" />
<input type="text" ng-model="offer.uri" />
<select ng-model="offer.network"
ng-options="n.id as n.name for n in networks">
</select>
</div>
</div>
The problem is that this always gives me a blank option as the first option whenever I try to set the model for the to offer.network. I have read
Why does AngularJS include an empty option in select?
and
AngularJS - extra blank option added using ng-repeat in select tag, but they only seem to apply to selects that are at the top level (i.e., not using a model inside an ng-repeat). My problem is that I need to update a model that is part of a nested ng-repeat.
EDIT: I should have also included the below code; this is what is actually breaking everything. This code runs after the original array is set up:
$scope.getNetworks = function () {
$http.get('/api/networks/nameid'
).success(function (data, status, headers, config) {
$scope.networks = data;
});
};
$scope.getNetworks();
The above backend call returns an array of objects of the form {id: id, :name "name"}.
And yes, I could populate the select statically from the server side, but I would really like to know how to make this work in the general case.
Since you use the n.id in the comprehension expression of the drop down list, you should pre-populate the offer.network with the id value like this
network: $scope.networks[0].id
And since the data is populated dynamically, you can do something like this. (For the demo purpose, I just use a very dumb way to populate the values. But you get the idea.)
$scope.getNetworks().then(function(data){
$scope.networks = data;
//populate the default value
$scope.campaign.paths[0].offers[0].network = $scope.networks[0].id;
$scope.campaign.paths[0].offers[1].network = $scope.networks[0].id;
})
Working Demo