Making the Bootstrap navbar searchbox work - angularjs

I am trying to make a search function which works if I put in the query params into my URL directly but I don't know how to make it work so that it picks it up from the search box and executes it. I have used ng-model to map the text itself to the controller which works but the execution isn't working.
The navbar form:
<form ng-submit="doSearch()" class="navbar-form">
<div class="form-group" style="display:inline;">
<div class="col-md-offset-4 input-group" style="display:table;">
<input ng-model="search.text" class="form-control" name="search" placeholder="Search Here" autocomplete="off" autofocus="autofocus" type="text">
<span class="input-group-addon" style="width:1%;">
<span class="glyphicon glyphicon-search"></span>
</span>
</div>
</div>
By the way, my doSearch() function works just fine when I run it manually and so is the search itself. I have also validated that search.text comes through. I guess what I am asking is how do I make the icon (glyphicon-search) execute ng-submit="doSearch()" when the user clicks on it or presses enter.
Sorry if this is very obvious. I was always more on the backend side of things so am sorta new to HTML and Angular.
Thanks

You could place the icon inside a <button> element instead of <span>, tweak a bit of css to integrate it to the form field.
In regards to trigger search on enter, with jQuery something like this could be used:
$('input').keypress(function (e) {
var key = e.which;
if(key == 13) // the enter key code
{
doSearch();
}
});

did you try using <button type="submit"> before your search icon
<span class="glyphicon glyphicon-search"></span>
to specify that clicking on that button is equivalent to a submit event for that form.

So this worked in the end. First, the proper HTML which works:
<form ng-submit="doSearch()" class="navbar-form">
<div class="form-group" style="display:inline;">
<div class="col-md-offset-4 input-group" style="display:table;">
<input ng-model="search.text" class="form-control" name="search" placeholder="Search Here" autocomplete="off" autofocus="autofocus" type="text">
<span ng-click="doSearch()" class="input-group-addon" style="width:1%;">
<span class="glyphicon glyphicon-search"></span>
</span>
</div>
</div>
</form>
Furthermore, there was an issue with the view not connecting to the controller. Actually, let me rephrase that - it was connecting to the controller but only when the whole page loaded and for my test, I had a console.log('I have loaded') put in there. So when I saw "I have loaded", I thought my controller was invoked properly.
However, the doSearch() was in the controller which was connecting via angular routing, so the ng-View was not connecting to the right controller.
I am not sure if this means anything to anyone but I am writing this in case someone else comes across an issue like mine.
So just to summarise the issue was not with the HTML as I originally thought. ng-submit (for form submission when pressing enter) and ng-click (for clicking the glyphicon) does the trick.

Related

AngularJS UI Bootstrap Typeahead not working as expected

I'm building a small search app using Elasticsearch and AngularJS. I'm using AngularJS UI bootstrap typeahead to implement autocomplete and I'm using ES's edge_n_grams and highlight object to 1) generate the suggestions and 2) highlight the suggestions, respectively. ES highlight object wraps the suggestions in HTML <em></em> tags... which seems to be causing some issues with how I have things setup.
1) When I press Enter key instead of clicking on the search button - all that happens is the search terms are displayed wrapped in the <em></em> tags AND no search is performed... <em>search terms</em>
2) When I select a suggestion with the mouse, same thing happens.
The only time search performs is when I type a query in and click the search button...
Here is the search form that I'm using, I have ng-submit="search()" on the form element and on the button, not sure where I'm going wrong......?
<form name="q" ng-submit="search()" class="navbar-form" id="results-search" role="search">
<div class="input-group">
<input type="text" name="q" ng-model="searchTerms" class="form-control input-md" placeholder="{{ searchTerms }}" id="search-input" uib-typeahead="query for query in getSuggestions($viewValue)" typeahead-on-select="search($item)">
<div class="input-group-btn">
<button type="submit" ng-submit="search()" class="btn btn-primary btn-md"><i class="fa fa-search fa-lg"></i></button>
</div>
</div>
</form>
Am I doing something wrong with the UI Bootstrap Typeahead?
More clarification
So basically what I'm asking is how do I get the tags stripped from the suggestions, on selection and for searching?
Similar kind of example already asked in Stackoverflow: Click here

ngClick does not fire inside label tag

I am trying to fire a click event to toggle show password. That's my code:
HTML
<div class="show-password" ng-click="toggleShowPassword();">
<i class="ion-ios-eye-outline" ng-show="!showPassword"></i>
<i class="ion-ios-eye" ng-show="showPassword"></i>
</div>
<label>
<input type="password" ng-model="myPassword" ng-show="!showPassword">
<input type="text" ng-model="myPassword" ng-show="showPassword">
</label>
JS
$scope.showPassword = false;
$scope.toggleShowPassword = function() {
$scope.showPassword = !$scope.showPassword;
}
The problem is: Outside of <label>, the funcition works fine (above). But if I place the <div class="show-password"> inside of <label>, the function toggleShowPassword() just won't work.
Should I really place the div insde of label ou just leave it this way? (It's working anyway, but it does not feel right).
Is there another way to achieve this function?

router::url doesn't work in the same controller

I have this form:
<div id="buscador">
<form action="<?php echo Router::url(array('controller'=>'categorias','action'=>'buscar'));?>" name="form_search" id="form_search" method="post" >
<input type="text" name="search">
<input type="submit" value="Buscar" class="buscador" id="boton_buscar"/>
</form>
</div>
It works fine in all controllers except when you are using the controller "categorias"... in that case, the result is this: http....Categorias/buscar/Buscar
Any idea why this happens?
The problem was present elsewhere, I didn't consider that when clicking the button inside the View "buscar", then JS acts on that click (and this generates the buscar/Buscar problem)

Why is click ignored on non-Angular page in a Protractor test?

I have an app I'm trying to do e2e tests with. The app uses a non-Angular login page (Microsoft AD account). So, I fill in the user and password then click the "sign in" button with the following code:
var user = asAdmin ? config.adminUser : config.user;
browser.driver.findElement(by.id('cred_userid_inputtext')).sendKeys(user);
browser.driver.findElement(by.id('cred_password_inputtext')).sendKeys(config.pass);
browser.driver.findElement(by.id('cred_sign_in_button')).click();
The user and password get filled in and the "sign in" button (which is a <span>) looks like it was clicked (changes color), but nothing happens.
I wait for quite a while (minutes) and it just doesn't work. However, if I just use the mouse, it does work. I have also tried tacking on a "\n" to the end of the password string to simulate the enter key. This is ignored.
The html for the pertinent parts of the login look like this:
<form id="credentials" method="post" action="https://login.microsoftonline.com/...">
<div id="cred_userid_container" class="login_textfield textfield">
<span class="input_field textfield">
<label for="cred_userid_inputtext" class="no_display" aria-hidden="true">User account</label>
<div class="input_border">
<input tabindex="1" id="cred_userid_inputtext" class="login_textfield textfield required email field normaltext" placeholder="someone#example.com " type="email" name="login" spellcheck="false" alt="someone#example.com " aria-label="User account" value="" autocomplete="off">
</div>
</span>
</div>
...
<div id="cred_password_container" class="login_textfield textfield" style="opacity: 1;">
<span class="input_field textfield">
<label for="cred_password_inputtext" class="no_display" aria-hidden="true">Password</label>
<div class="input_border">
<input tabindex="2" id="cred_password_inputtext" class="login_textfield textfield required field normaltext" placeholder="Password" spellcheck="false" aria-label="Password" alt="Password" type="password" name="passwd" value="">
</div>
</span>
</div>
...
<li class="login_cred_options_container">
<div id="cred_kmsi_container" class="subtext normaltext">
<span class="input_field ">
<input tabindex="10" id="cred_keep_me_signed_in_checkbox" type="checkbox" value="0" name="persist">
<label id="keep_me_signed_in_label_text" for="cred_keep_me_signed_in_checkbox" class="persist_text">Keep me signed in</label>
</span>
</div>
<span id="cred_sign_in_button" tabindex="11" onclick="Post.SubmitCreds();return false;" class="button normaltext cred_sign_in_button refresh_domain_state disabled_button" role="button" style="opacity: 1;">Sign in</span>
<div id="recover_container" class="subtext smalltext" style="opacity: 1;">
<span>
<a id="cred_forgot_password_link" tabindex="12" href="https://login.microsoftonline.com/resetpw.srf?lc=1033&id=501148">Can’t access your account?</a>
</span>
</div>
</li>
...
</form>
I can't, for the life of me figure out what's going on here.
Any help is greatly appreciated.
UPDATED: added the missing "button" span
UPDATE 2: also tested with Firefox, same problem. The click on the span just doesn't seem to work..
UPDATE 3: For some strange reason, the following code works:
browser.actions()
.mouseMove(browser.driver.findElement(by.id('cred_sign_in_button')))
.click()
.perform();
browser.sleep(500);
browser.driver.findElement(by.id('cred_sign_in_button')).click();
If I take either the mouseMove/click or the last click out, it stops working. If I take out the sleep, it is intermittent.
I have no idea why that's working.
Testing non-angular pages with Protractor can be tricky regarding waiting for stuff.
I suggest you upgrade Protractor to latest (1.3.1 as of now), use a custom function waitReady() that browser.wait for elements ready and rewrite your test like this:
var user = asAdmin ? config.adminUser : config.user;
// TODO: use page objects
var userIdInputElm = $('#cred_userid_inputtext');
var passwordInputElm = $('#cred_password_inputtext');
var signinButtonElm = $('#cred_sign_in_button');
it('waits for the elements present and visible (non-angular)', function() {
expect(userIdInputElm.waitReady()).toBeTruthy();
expect(passwordInputElm.waitReady()).toBeTruthy();
expect(signinButtonElm.waitReady()).toBeTruthy();
});
it('fills user and password', function() {
userIdInputElm.sendKeys(user);
passwordInputElm.sendKeys(config.pass);
});
it('clicks sign in button', function() {
signinButtonElm.click();
});
More details of why waitReady here.

AngularJS not validating email field in form

I have the html below where I have a form that I want to submit to the AngularJS Controller.
<div class="newsletter color-1" id="subscribe" data-ng-controller="RegisterController">
<form name="registerForm">
<div class="col-md-6">
<input type="email" placeholder="your#e-mail.com" data-ng-model="userEmail" required class="subscribe">
</div>
<div class="col-md-2">
<button data-ng-click="register()" class="btn btn-primary pull-right btn-block">Subsbcribe</button>
</div>
</form>
</div>
And the controller is below
app.controller('RegisterController', function ($scope,dataFactory) {
$scope.users = dataFactory.getUsers();
$scope.register = function () {
var userEmail = $scope.userEmail;
dataFactory.insertUser(userEmail);
$scope.userEmail = null;
$scope.ThankYou = "Thank You!";
}
});
The problem is that no validation is taking place when I click the button. It is always routed to the controller although I do not supply a correct email. So every time I click the button I get the {{ThankYou}} variable displayed. Maybe I do not understand something.
AngularJS does not disable enable any functionality for form validations. What is does is, it makes the state of the form and its control in terms of validation available on the current scope. You are required to implement the behaviour yourself.
In your case if you need to check user email is valid your html input should have a name attribute like
<input type="email" placeholder="your#e-mail.com" data-ng-model="userEmail" required class="subscribe" name='userEmail'>
Then on your controller you can check
$scope.registerForm.userEmail.$invalid property.
You can use the same property to disable the button on the form using ng-disabled
<button data-ng-click="register()" class="btn btn-primary pull-right btn-block" ng-disabled='registerForm.userEmail.$invalid'>Subsbcribe</button>
Basically the registerForm object is a ngFormController and userEmail is ngModelController. Please read the developer guide for forms
You are missing some part to achieve what you want. Normally you will need to add some code to enable disable the submit button base on the state of the form i.e valid/invalid. In your case this can be done like that :
<button data-ng-click="register()" class="btn btn-primary pull-right btn-block" ng-disabled="registerForm.$invalid">Subsbcribe</button>
Notice the ng-disabled="registerForm.$invalid".
You can as well provided inline feedback to the user with something like :
<input type="email" placeholder="your#e-mail.com" data-ng-model="userEmail" required="" class="subscribe" name="userName"/>
<span ng-show="registerForm.userName.$error.required">Please enter a name</span>
Or with CSS like that :
input.ng-invalid-required {
background-color: #FA787E;
}
You have a working plunker here

Resources