Angular Js: Typeahead - html

I have an input type which uses angularjs type-ahead.The problem I am facing is that it disappears when I move my mouse over it. I am able to use the arrow keys to select items from the list,but am unable to click and select from the list.
I am getting list from the database,and the typeahead list is populating fine. Other places I used almost the same code,it works fine. When using this particular typeahead, after a while,say 5-6 trials, it behaves normally.
Any help will be appreciated.Thanks.
My html:
<input
id="{{roleAssignmentTableDTO.employeeNumberElementId}}" type="text"
name="employeeNumber"
ng-disabled="roleAssignmentTableDTO.disableEmployee"
ng-model="roleAssignmentTableDTO.employeeNumber"
typeahead="state for state in states | filter:$viewValue" />
My Controller:
$http
.post('rest/employeeSearch', query)
.success(
function(dataList) {
/*$scope.roleAssignmentDTO.roleAssignmentTableDTOList[elementId].searchLoader = false;
roleAssignmentTableDTO.showSearchLink=true;*/
if (dataList.length == 0) {
/*$scope.projectNotfoundError = true;
$scope.roleAssignmentDTO.roleAssignmentTableDTOList[elementId].showSearchLink = false;
$scope.projectNotfoundErrorMsg = 'You entered incorrect employee';*/
}
$.each(
dataList,
function(
i,
data) {
map[data.employeeNumber] = data;
List
.push(data.employeeNumber);
});
process(List);
})
.error(
function() {
$scope.roleAssignmentDTO.roleAssignmentTableDTOList[elementId].searchLoader = false;
$scope.projectNotfoundError = true;
$scope.projectNotfoundErrorMsg = 'Some Internal error occured';
List
.push("no data found");
process(List);
});
},
updater : function(selectedData) {
$scope.roleAssignmentDTO.roleAssignmentTableDTOList.employeeNumber = selectedData;
return selectedData;
}
});

Related

How to use one request to local JSON file to populate multiple dropdowns, using jQuery?

I am trying to use Country/City dropdowns in multiple places of my project, however I am getting stuck with an unusual behaviour - when I am changing the countries. How can I make one request to get the local JSON file and populate multiple dropdowns?
Here is my code:
$(document).ready(function() {
fetch('assets/test.json').then(response => {return response.json()}).then(selectData => {
console.log(selectData)
function updateSelectsBirth() {
let citiesBirth = selectData[this.value].map((key, val) => {
return $("<option />").text(key).val(key);
});
$("#cityBirth, #cityBirth1").empty().append(citiesBirth);
}
let stateBirth;
$countryBirth = $("#countryBirth, #countryBirth1").on("change", updateSelectsBirth);
for (stateBirth in selectData) {
$("<option />").text(stateBirth).val(stateBirth).appendTo($countryBirth);
}
$countryBirth.change();
})
});
And the HTML
<select id="countryBirth"></select>
<select id="cityBirth"></select>
<br/>
<select id="countryBirth1"></select>
<select id="cityBirth1"></select>
Here's also a link to the demo project: link to the demo
The unexpected behaviour comes from
$("#cityBirth, #cityBirth1").empty().append(citiesBirth);
Because, when it's updating the cities, it's updating all the dropdowns instead of just one.
So you can try:
$(document).ready(function() {
fetch('assets/test.json').then(response => {return response.json()}).then(selectData => {
// console.log(selectData)
function updateSelectsBirth(event) {
let citiesBirth = selectData[this.value].map((key, val) => {
return $("<option />").text(key).val(key);
});
// console.log(event.data.target)
$(event.data.target).empty().append(citiesBirth);
}
let stateBirth;
$countryBirth = $("#countryBirth").on("change", {target: "#cityBirth"}, updateSelectsBirth);
$countryBirth1 = $("#countryBirth1").on("change", {target: "#cityBirth1"}, updateSelectsBirth);
// $countryBirth1 = $("#countryBirth1").on("change", updateSelectsBirth("#cityBirth1"));
for (stateBirth in selectData) {
$("<option />").text(stateBirth).val(stateBirth).appendTo($countryBirth);
$("<option />").text(stateBirth).val(stateBirth).appendTo($countryBirth1);
}
$countryBirth.change();
$countryBirth1.change();
})
});
I apologize this is not a complete answer, as I'm not generalizing to multiple dropdowns, however I am not able to leave comments yet. I hope this can still be helpful.

Why does the ToolController's getPriority return 0 for my tool?

According to a prior SO answer, you can implement getPriority for a forge viewer Tool. And according to another SO answer extending the ToolInterface does not work. Hence, me not extending the ToolInterface implementing my Tool like so:
class MyCustomExtension extends Autodesk.Viewing.Extension {
constructor(viewer, options) {
super(viewer, options);
this.theiaUtil = new TheiaUtil(this);
}
getPriority() {
console.log("Theia#getPriority called! ", (this.getPriority && this.getPriority() || 0));
return 100000;
}
...
}
My tool's priority is returned as 0 in the ToolController, although it shouldn't:
function getPriority(tool)
{
return tool.getPriority instanceof Function && tool.getPriority() || 0;
}
I don't know why this function returns 0 as tool.getPriority instanceof Function returns true if I call MyCustomExtension.getPriority myself.
Note that ToolInterface is implemented like so:
function ToolInterface()
{
this.names = [ "unnamed" ];
this.getNames = function() { return this.names; };
this.getName = function() { return this.names[0]; };
this.getPriority = function() { return 0; };
this.register = function() {};
this.deregister = function() {};
this.activate = function(name, viewerApi) {};
this.deactivate = function(name) {};
this.update = function(highResTimestamp) { return false; };
this.handleSingleClick = function( event, button ) { return false; };
this.handleDoubleClick = function( event, button ) { return false; };
this.handleSingleTap = function( event ) { return false; };
this.handleDoubleTap = function( event ) { return false; };
// ...
}
Because of that, simply extending the ToolInterface class won't work because all these properties and functions added to the instance in the constructor will take precedence over your actual class methods. This is also likely the reason why you're seeing the priority value returned as zero - when you call myTool.getPriority(), you are not actually calling your getPriority method, but rather the default function which was assigned to this.getPriority in ToolInterface's constructor.
To work around this issue I would recommend explicitly deleting the corresponding fields in your class' constructor (something I explain in my blog post on implementing custom Forge Viewer tools):
class DrawTool extends Autodesk.Viewing.ToolInterface {
constructor() {
super();
this.names = ['box-drawing-tool', 'sphere-drawing-tool'];
// Hack: delete functions defined *on the instance* of the tool.
// We want the tool controller to call our class methods instead.
delete this.register;
delete this.deregister;
delete this.activate;
delete this.deactivate;
delete this.getPriority;
delete this.handleMouseMove;
delete this.handleButtonDown;
delete this.handleButtonUp;
delete this.handleSingleClick;
}
register() {
console.log('DrawTool registered.');
}
deregister() {
console.log('DrawTool unregistered.');
}
activate(name, viewer) {
console.log('DrawTool activated.');
}
deactivate(name) {
console.log('DrawTool deactivated.');
}
getPriority() {
return 42; // Or feel free to use any number higher than 0 (which is the priority of all the default viewer tools)
}
// ...
}
TL;DR: Activate the tool in button click event from a toolbar button instead of the extension's load method.
class MyExtension extends Autodesk.Viewing.Extension {
...
onToolbarCreated(toolbar) {
const MyToolName = 'My.Tool.Name'
let button = new Autodesk.Viewing.UI.Button('my-tool-button');
button.onClick = (e) => {
const controller = this.viewer.toolController;
if (controller.isToolActivated(MyToolName)) {
controller.deactivateTool(MyToolName);
button.setState(Autodesk.Viewing.UI.Button.State.INACTIVE);
} else {
controller.activateTool(MyToolName);
button.setState(Autodesk.Viewing.UI.Button.State.ACTIVE);
}
};
}
...
}
I activated the tool instantly after registering it in the Extension's load method. Petr Broz's github repo from his blog post loads the tool from a button in the toolbar. So I moved the activation of the tool to a button click in the toolbar which worked for me.

Angular Detect change on html input element or trigger it automatically

I want to get the value of an input element once it changes. The value is not typed by the user. I got it from a source and bind it with [(ngModel)] or just [value]. I have tried everything. But I still got nothing. I even search on how to trigger an event manually. if some of you can help me, I would be grateful
My code: I have tried various things. But this is the one that seems to work. But this instructions in the subscribe method was executed twice
this.maxGroup$ = this.reponseService.getMaxGroupe();
this.maxGroup$.subscribe((rep: MaxGroup) => {
if (rep) {
this.maxGroupe = rep;
this.max = rep.valeur;
this.questions.forEach(q => {
let r = new Reponse();
r.QuestionId = q.Id.toString();
r.Question = q;
r.Groupe = rep.valeur;
this.reponses.push(r);
});
}
this.max++;
this.maxGroupe.valeur = this.max;
let ref = this.reponseService.createMax(this.maxGroupe);
this.reponseService.deleteMax(this.idMax);
});
In my service:
return this.db.list('/maxGroup').snapshotChanges().map(snapshots => {
return snapshots.map(c => ({ key: c.payload.key, ...(c.payload.val()) as {} }));
});
In my template:
<div *ngFor="let m of maxGroup$ | async">
<input #KeyMax type="text" id="keyMax" [(ngModel)]="m.key" [value]="m.key" (change)="keyChange()"/>

Scope value not updating in view in IONIC 1 and Angular js

I have a requirement like saving two previous login details.
I am done with it. But my view will update only on refresh.But scope values are updated.
Tried with scope.apply,digest,timeout. But nothing seems to work here.
$scope.loginUserName=localStorage.getItem("loginUserName");
$scope.userName=localStorage.getItem("userName");
$scope.mobileNumber=localStorage.getItem("mobileNumber");
$scope.loginData = {};
$scope.userLogin = function(loginData) {
userService.userLogin(loginData).then(function(success) {
var res=success.message;
if(res==='success'){
if(localStorage.getItem("userName1")==null || localStorage.getItem("userName1") == success.firstName){
localStorage.setItem("userName1",success.firstName);
localStorage.setItem("loginUserName",success.firstName);
}else if(localStorage.getItem("userName2")==null || localStorage.getItem("userName2") == success.firstName ){
localStorage.setItem("userName2",success.firstName);
localStorage.setItem("loginUserName",success.firstName);
}
localStorage.setItem("userName",success.firstName);
$scope.userName=success.firstName;
$scope.mobileNumber = success.mobileNumber;
$scope.loginData = {};
$state.go('app.home');
}else{
$scope.message ='Wrong pin.Try again or click Forgot password to reset it.';
}
},function(error){
});
};
$scope.loginPerson = function(mobileNumber,userName){
localStorage.setItem("loginUserName",userName);
// here userName is updating,but not reflecting in view
$scope.loginUserName=localStorage.getItem("loginUserName");
//setTimeout(function(){ $scope.$apply(); });
console.log("In loginPerson:"+userName);
$state.go('app.start');
}
start.html
<span ng-if="loginUserName !=null">
<p class="startP">Enter pin for {{loginUserName}}
<i class="icon ion-chevron-down" ui-sref="app.loginOptions">
</i></p>
</span>
State
//Here is the state details,I have same controller for two state.
.state('app.loginOptions', {
url: '/loginOptions',
views: {
'menuContent': {
templateUrl: 'templates/loginOptions.html',
controller:'LoginCtrl'
}
}
})
.state('app.start',{
url:'/start',
views:{
'menuContent':{
templateUrl:'templates/start.html',
controller:'LoginCtrl'
}
}
EDIT
I have used within object also,But nothing is changed.
step 1) please use angular copy while get data from localstorage to $scope $scope.xyz=angular.copy(localstorage.get('key'))
after implement step 1 then not work use $scope.$apply(); after set value in $scope.
try to use loginUserName as a property of an object instead a property of scope directly. Sometimes angularjs fail to update view for these values.
Like
$scope.data={
loginUserName:""
};
Then inside your function
$scope.userLogin = function(loginData) {
...
$scope.data.loginUserName=localStorage.getItem("loginUserNa‌​me");
// To check it
console.log($scope.data);
}
html
<span ng-if="data.loginUserName !=null">
...
</span>
Update
Change the loginPerson function like below.
$scope.loginPerson = function(mobileNumber,userName){
localStorage.setItem("loginUserName",userName);
$scope.data.loginUserName=localStorage.getItem("loginUserName");
console.log("In loginPerson:"+userName);
console.log($scope.data);
}

Typeahead each time user writes a certain word

I'm using the ui-bootstrap typeahead for when a user types to show all the variables available for him to write which are proprieties from an object which is loaded Ex: item.cost+item.quantity.
My question is I want the suggestions only to appear each time user types "item.", I've notice the typeahead only works for one word and at the beginning.
html
<div class="modal-body">
Add expression:
<textarea style="width: 568px;" ng-model="item.formula"
uib-typeahead="state for state in states "
typeahead-show-hint="true"
typeahead-on-select="item"
ng-change="eval(item.formula)">
</textarea>
<p><b>Result:</b> <br>
<div style="width: 100%">{{ans}}
</div>
</p>
</div>
controller
ctrl.controller('myController', ['$scope', function ($scope) {
$scope.imageShowModal = function (item) { //loads the object items
$scope.item = item;
$scope.states =Object.keys(item); //get the JSON keys from item object like cost,price,quantity,workflow...
};
$scope.eval = function (v) {
try {
$scope.ans = $scope.$eval(v);
} catch (e) {
}
};
You can use a custom filter in your uib-typeahead expression, ex: uib-typeahead="state for state in states | myCustomFilter:$viewValue"
A custom filter in your case might look like this:
angular.module('myApp')
.filter('myCustomFilter', function() {
return function(list, term) {
if (term.indexOf('item.') === -1)
return [];
var filteredList = [];
angular.forEach(list, function(value) {
if (value.indexOf(term) !== -1)
filteredList.push(value);
});
return filteredList;
}
});
See also: AngularJs UI typeahead match on leading characters