md-autocomplete doesn't work after once - javascript

I've made a simple auto complete functionality on text search. There are two functions - querySearch(searchText) and homeresults(item). The querySearch function correctly fetches the results and there is no issue there. Once a result is selected by the user, then it calls homeresults function. This function works fine for the first time, but doesn't work after that unless I return to home page. So once a user is on results page, he can't use the search bar again unless he comes back to home page. There are no errors. Here is my code snippet:
HTML
<form ng-submit="$event.preventDefault()">
<md-autocomplete md-selected-item="selectedItem" md-search-text="searchText" md-items="item in querySearch(searchText)" md-item-text="item.title" md-delay="400" md-min-length="2" md-floating-label="Search for any Query">
<div layout-align="start center">
<span md-highlight-text="searchText" ng-click="homeresult(item)">{{item.title}}</span>
</div>
<md-not-found>No matches found </md-not-found>
</md-autocomplete>
Javascript
$scope.querySearch = function(search) {
var key = $scope.searchText;
console.log('keyword searched by user is ' + key);
return $http.get('/api/searchresult?title=' + key)
.then(function(response) {
return response.data
});
};
$scope.homeresult = function(item) {
console.log(item);
$timeout(function() {
item.title = item.title.replace(/ /g, '-');
$location.url('/results').search({
"title": item.title
})
}, 50);
};

In the homeresult(), code is redirecting to /results. So, instead of redirection, if you show results on the same page where md-autocomplete is defined, it will work. You can add a simple check to hide the results until we get response from $http.

Related

Unable to get the value from an array of object in md-autocomplete

I have an array of objects, and Now I am trying to select the data. Enclosed file is a snapshot of the object I am getting in console.
I want to get the emailid even if user search by the empid or empname or emailid from the object in autocomplete.
But I am unable to retrieve this one when I start typing in md-autocomplete my screen blinks and never gave me list of filter items.
Updated code :
<md-autocomplete flex required
md-search-text="searchText"
md-input-name="autocomplete"
md-search-text-change="searchTextChange(searchText)"
md-items="item in search(searchText)"
md-item-text="item"
md-floating-label="Reporting Manager">
<md-item-template>
<span md-highlight-text="searchText" md-highlight-flags="^i">{{item.empname}}</span>
</md-item-template>
</md-autocomplete>
And this is my javascript search() function
$scope.search = function(text){
var deferred = $q.defer()
var result = []
var resolve = function(reportingManager){
//console.log(reportingManager)
angular.forEach(reportingManager,function(val){
//console.log(val)
angular.forEach(val,function(value){
//console.log(value)
if(value.empid.toUpperCase().includes(text.toUpperCase())
|| value.empname.toUpperCase().includes(text.toUpperCase())){
result.push(value.empname)
//console.log(result)
}
})
})
deferred.resolve(result)
}
if(text){
resolve(reportingManager? reportingManager: [])
}else{
resolve([]);
}
return deferred.promise
}
reportingManager is an array of arrays which has the objects which i have included in the snapshot.
Any help on this one would be highly appreciable
Regards
First of all I would like to thank #Titus for being there for me and walking with me to solve my problem.
The issue was not only with Javascript code it was also with CSS. Since I was trying to put the md-autocomplete in a modal pop up after so many trials the autocomplete suggestions were coming up but it was behind the modal. Here is the working code
$scope.search = function(text){
var deferred = $q.defer()
var result = []
var resolve = function(reportingManager){
//console.log(reportingManager)
angular.forEach(reportingManager,function(val){
//console.log(val)
angular.forEach(val,function(value){
//console.log(value)
if(value.empid.toUpperCase().includes(text.toUpperCase())
|| value.empname.toUpperCase().includes(text.toUpperCase())){
result.push(value.emailid)
//console.log(result)
}
})
})
deferred.resolve(result)
}
if(text){
resolve(reportingManager? reportingManager: [])
}else{
resolve([]);
}
return deferred.promise
}
HTML :
<div class="md-virtual-repeat-container">
<md-autocomplete flex required
md-search-text="searchText"
md-input-name="autocomplete"
md-search-text-change="searchTextChange(searchText)"
md-items="item in search(searchText)"
md-item-text="item"
md-selected-item="selectedManager"
md-floating-label="Reporting Manager">
<md-item-template>
<span md-highlight-text="searchText" md-highlight-flags="^i">{{item}}</span>
</md-item-template>
</md-autocomplete>
</div>
Psst **In case you are trying to get the autocomplete in a pop up don't forget to set the high value for z-index
And also include the $q in your controller

AngularJS - run check against elements as they come back

I just followed this
JSFiddle example to create a little search box from an array object in my javascript. Now after some tweaking and research on search.object and filter:search:strict. Now that I have it filtering correctly, I modified a checkbox in the template that is checked upon loading the document and switched on or off based on a custom data attribute in the html that is updated by the json array.
How do I run this check once someone clears the search and the old items show back up again?
In the HTML I have this template
<div ng-repeat="o in objects | filter:search:strict | orderBy:'obj_name'" class="objectContainer">
<h3>{{o.obj_name}}</h3>
<label class="userToggleSwitch" >
<input class="userToggleInput" data-isactive="{{o.obj_isactive}}" type="checkbox">
<div class="slider round"></div>
</label>
</div>
In the JS
angular.element(document).ready(function(){
angular.module('searchApp',[])
.controller('searchCtrl', ['$scope','objHolder',function ($scope,objHolder) {
$scope.search = '';
$scope.objects = [];
$scope.objects = objHolder.getobjects();
}])
// fake service, substitute with your server call ($http)
.factory('objHolder',function(){
var objects = objList;
return {
getobjects : function(){
return objects;
}
};
});
});
The JS that modifies the items on document load is using jquery like this
$(document).ready(function(){
//console.log($('.userToggleInput'));
$.each($('.userToggleInput'), function(){
if($(this).data("isactive") == 1){$(this).attr('checked', true);}
if($(this).data("isactive") == 0){$(this).attr('checked', false);}
})
$('.userToggleInput').click(function(){
if ($(this).attr('checked') == undefined) {
// THIS IS WHERE WE WILL MAKE AN AJAX CALL TO A PHP CLASS
// TO REQUEST IF THE USER CAN BE TURNED ON - DUE TO LIC RESTRICTIONS
$(this).attr('checked',true);
} else {
$(this).attr('checked',false);
}
//console.log($(this).attr('checked'));
});
});
Created JS Fiddle to assist in Helping in this manner

$.getJson won't affect view until event

Didn't really know how to word the question. Using angular. Anyways, I'm trying to have it so when the user types in the text box a state, once it has been verified that the state exists (comparing to an array of all 50), it will automatically call a getJSon Jquery request for a JSON object. But for some reason, it doesn't execute right away, instead I have to press a key after doing so.
Code:
$scope.checkState = function(team) {
//check for team
console.log("Searching for " + document.getElementById('team').value)
var teamFind = document.getElementById('team').value;
var team = $.inArray(teamFind, $scope.states);
console.log("team: " + team);
if (team == -1)
{
console.log("Not found");
$scope.selectedState = "Not Found";
teamFound = false;
}
//correct team
if (team > -1)
{
$.getJSON('https://api.myjson.com/bins/1ak21r', function (data) {
//console.log(data.bowl);
$scope.items = data;
console.log($scope.items);
console.log("Team Bowl: " + team_bowl)
console.log("Found: " + $scope.states[team]);
$scope.selectedState = $scope.states[team];
teamFound = true;
});
}
}
html code
<p class="w3-large w3-center">
<input type="text" name="team" id="team" value="Whats Your Team?" ng-keyup="checkState(team)">
</p>
<p class="w3-jumbo w3-center">
<span id="bowl">{{ selectedState }}</span>
</p>
<p class="w3-large w3-center">
<span>f{{ items }}</span>
</p>
</div>
I know it might be hard to understand what I want, but I was creating a sample application that would show what bowl game a team was competing in. The user types the team into the text-box id=team below, and I wanted it done without them having to press enter or submit.
On the key-up, it runs the check function. So for example, once Maryland is entered, the getJson will run and correctly logs the data, but the $scope.items isn't updated until after I type one more key AFTER I entered the state
So like typing:
M-A-R-Y-L-A-N-D(CONSOLE LOGS THE JSON OBJECT CORRECTLY, BUT ON THE HTML {{ items }} STILL SHOWS NOTHING)-any_key_here(NOW IT GETS UPDATED)
Thanks for any help.
EDIT:
So I was able to get it by having another function be called with the data inside the JSON function.
myFunction(data);
which calls
function myFunction(items) {
console.log(items);
document.getElementById('bowl2').innerHTML = items.team;
};
You are using jQuery's ajax method which does not integrate with angular to inform angular when it is done. It's best to use angular's built in $http methods which do the same thing expect when they complete they trigger a digest cycle which will update the view.
You will need to inject $http into your controller or service (depending on where this code lives) in order to use it. Once you do that, you should be able to make the following modification to you code.
Change
$.getJSON('https://api.myjson.com/bins/1ak21r', function (data) {
//console.log(data.bowl);
$scope.items = data;
console.log($scope.items);
console.log("Team Bowl: " + team_bowl)
console.log("Found: " + $scope.states[team]);
$scope.selectedState = $scope.states[team];
teamFound = true;
});
to
$http.get('https://api.myjson.com/bins/1ak21r')
.then(function (response) {
var data = response.data;
//console.log(data.bowl);
$scope.items = data;
console.log($scope.items);
console.log("Team Bowl: " + team_bowl)
console.log("Found: " + $scope.states[team]);
$scope.selectedState = $scope.states[team];
teamFound = true;
});

ngRepeat not updating even though list is

I'm having a problem where despite a list being updated, ngRepeat does not display the information.
In the code below, the $scope.selectedImages array is being added to when images are selected using the file input. It is set up so that only unique files will be added to the list of selectedImages (no duplicates).
At the end of the function, scope.selectedImages prints the array with the new values, but in the view, ngRepeat does not add the new list items with the image names.
Other questions regarding this issue said that $scope.$apply should fix the problem, but for me it is not. Am I using it wrong or is there something else that I am misunderstanding.
EDIT: View 1 and View 2 are in separate HTML pages that both rely on the same controller.
View 1:
<input type="file" multiple accept="image/*" class="file-input" id="img-upload-btn" onchange="angular.element(this).scope().select(this)">
<md-button class="md-primary md-raised sidenav-btn" ng-click="proxy('img-upload-btn')">
Select <strong>Images</strong>
</md-button>
The proxy function allows the md-button to click the input.
View 2:
<div layout-padding flex ng-controller="upload-controller">
<ul>
<li ng-repeat="im in selectedImages">{{im.name}}</li>
</ul>
</div>
Controller:
$scope.selectedImages = [];
$scope.select = function(element) {
$scope.$apply(function(scope) {
var justFiles = $.map(element.files, function(val, key) {
return val;
}, true);
var fileEquality = function(f1, f2) {
if (f1.name != f2.name) return false;
if (f1.size != f2.size) return false;
if (f1.type != f2.type) return false;
if (f1.lastModified != f2.lastModified) return false;
return true;
}
// inefficient, find better way later
for (i in justFiles) {
var contains = false;
var file = justFiles[i];
for (i in scope.selectedImages) {
if (fileEquality(file, scope.selectedImages[i])) {
contains = true;
break;
}
}
if (!contains) scope.selectedImages.push(file);
}
console.log(scope.selectedImages);
});
};
Your input field template and controller template have to different scopes. Use $rootScope.selectedImages in your case.

multiple expression if else within ng-repeat

<div ng-repeat="book in books">
<h3 class="title">{{book.title}}</h3>
</div>
I use above code to get and it work fine, but I also have a search function, which will also set $scope.books. Unfortuunetly I have no control over the api, the search callback returned different scheme, means to get the title of the books I have to navigate to somewhere else, like book.category.item.title.
so I'm thinking of doing something like this
<a href="#/{{book.title || book.category.item.title}}">
check if book.title isset, else display another expression. Is it correct?
Instead I would prefer using ng-href
<a ng-href="{{getTitle()}}">link</a>
In your controller, return the url by checking logic there.
angular.module("app",[])
.controller("MainCtrl", function($scope) {
$scope.book = {};
$scope.book.title = null;
$scope.book.category = {
item : {
title : "Rafi"
}
}
$scope.getTitle = function() {
return '#/'+ ($scope.book.title || $scope.book.category && $scope.book.category.item && $scope.book.category.item.title);
}
});
DEMO
if you don't want to use controller for some reason:
<a ng-href="{{'#/'+(book.title || book.category.item.title)}}">

Categories

Resources