Using a search feature in angular js - javascript

I am trying to use the search feature in AngularJS (in Ionic framework). I have a template consisting of different views and a common header for all views. On each view, a different list appears using JSON. I want to use the search feature for each view.
<form class="form-inline">
<div class="form-group">
<input type="text" ng-model="search" class="form-control" placeholder="Search">
</div>
</form>
<ion-item class="item-button-right item-avatar item-icon-right item item-thumbnail-left" ng-repeat="text in texts|filter:search" type="item-text-wrap" href="#/otherContent/texts/{{text.id}}">
This code works fine if I use the above search form and ion-item in one single view. But does not work if I add search form in searchbar and put <ion-item> tag in the different page.
I hope this makes sense? Can anyone please suggest how can we implement this. I need searchbar in the header which is common for all views and it should search for each view when it is loaded. Any pointers are truly appreciated.

If you have a top level controller which is added to like html or body tag (if not then define a top level controller like GlobalController and add it to your <html> or <body> tag so that we can keep the global data there and it's scope can be globally accessible app-wide. Basically we are trying to avoid the $rootScope usage and mimicking the $rootScope usage.), then define an empty object in that global controller:
$scope.globalModel = {};
Then, change your ng-model like:
<input type="text" ng-model="globalModel.search" class="form-control" placeholder="Search">
And finally modify your search filter like:
<ion-item class="item-button-right item-avatar item-icon-right item item-thumbnail-left" ng-repeat="text in texts|filter:globalModel.search" type="item-text-wrap" href="#/otherContent/texts/{{text.id}}">
The above should work. What we are doing here is that defining an object in a parent scope so that we can prevent the problem of Angular Scopes Inheritance.

Related

I can't edit a object in an array, ng-model doesn't change with ng-click

I am making a movie library. I use ng-repeat to show the movies and, for each movie there is a button to edit it and another one to remove it. The remove button works just fine, but the edit button doesn't.
It should open a panel and fill it with the movie data, but it only opens the panel with the first value I defined for the index.
button
<i class="glyphicon glyphicon-pencil small btnEdit" ng-click="i =(movies.indexOf(movie));"></i>
input
<input type="text" class="form-control" placeholder="Title" id="title" ng-model="movies[i].title">
the whole code is here: https://jsfiddle.net/victoorns/mwgcnsno/2/
Your controller's $scope property 'i' is being hidden via the rules behind scope inheritance. Ng-repeat creates its own isolate scope and since 'i' is a primitive (its just an integer), 'i' is only being set on that child $scope, as opposed to the main parent controller's scope.
<input type="text" class="form-control" placeholder="Title" id="title"
ng-model="movies[selected.movieIndex].title">
<i class="glyphicon glyphicon-pencil small btnEdit"
ng-click="selected.movieIndex =(movies.indexOf(movie));"></i>
Heres an updated jsfiddle here.
Notice how I am using an object (selected.movieIndex) so that is correctly updating the right property.
Heres more on understanding the exact behavior going on with the scope here
Approach is putting too much business logic in the view.
Pass whole object back to controller when you do things like this. Then do any splicing, copying etc in controller:
Simplified example:
<div ng-repeat="movie in movies">
<button ng-click="edit(movie)">
<button ng-click="delete(movie)">
</div>
In controller:
$scope.delete = function(movie){
var idx = $scope.movies.indexOf(movie);
if(idx !=-1){
$scope.movies.splice(idx,1)
}
}
$scope.edit = function(movie){
$scope.selectedMovie = movie;
}
Also get rid of all the jQuery and get rid of bootstrap.js and replace with angular-ui-bootstrap

How would I create something similar like this in AngularJS

Having a hard time grasping AngularJs.. How would you build something like this simple textfields and animations in AngularJS? I had been looking into using directives but it just isn't adding up to me much. I had been trying to base this from what I learned online but was not having much luck
http://codepen.io/yusufbkr/pen/RPBQqg
HTML:
<div class="materialContainer">
<div class="title">LOGIN</div>
<div class="input">
<label for="name">Username</label>
<input type="text" name="name" id="name">
<span class="spin"></span>
</div>
<div class="input">
<label for="pass">Password</label>
<input type="password" name="pass" id="pass">
<span class="spin"></span>
</div>
<div class="button login">
<button><span>GO</span> <i class="fa fa-check"></i></button>
</div>
Forgot your password?
<div class="title">REGISTER</div>
<div class="input">
<label for="regname">Username</label>
<input type="text" name="regname" id="regname">
<span class="spin"></span>
</div>
<div class="input">
<label for="regpass">Password</label>
<input type="password" name="regpass" id="regpass">
<span class="spin"></span>
</div>
<div class="input">
<label for="reregpass">Repeat Password</label>
<input type="password" name="reregpass" id="reregpass">
<span class="spin"></span>
</div>
<div class="button">
<button><span>NEXT</span></button>
</div>
just use the codepen link ( http://codepen.io/yusufbkr/pen/RPBQqg ), stackoverflow won't let me input the rest of the code...
Thanks! Any help would be incredible
I'm just learning Angular myself. From what I know, you're on the right track to be thinking of directives for swapping out interactive parts of the DOM. I suspect you'll also be needing ui-router for dealing with the widget outcomes (I hear it's the industry standard, vs the built-in ngRouter).
I'm partly writing this out to make sure I understand it, so I hope other, more knowledgeable people will come by and answer any questions you have about it (or point out where I'm misundertanding something.)
So you bring the webpage into the Angular world by, for instance, making the <html></html> tags into <html ng-app="yourApp"></html>. The unchanging html that will be the same on every view is in the index.html file. Put the html for the boxes is in another html file, say box.html. On the index.html file in the place where you want to have your boxes appear, put <div ui-view></div>. The ui-view connects to ui-router. Down at the bottom of the index.html right before closing the body tag, put
<script src="lib/angular/angular.js"></script>
<script src="lib/angular-ui-router/release/angular-ui-router.js"></script>
<script src="app/app.js"></script>.
In app.js, you put something like,
angular.module('yourApp', [
'yourApp.box',
'ui.router'
])
.config(function($stateProvider, $urlRouterProvider, $httpProvider) {
$urlRouterProvider
.otherwise('/signin/child');
$stateProvider
.state('box', {
url: '/signin',
templateUrl: 'app/box/box.html',
controller: 'BoxController'
})
.state('box.child', {
url: '/child',
template: '<span>{{ definedProperty }}</span>'
});
})
});
Starting at the top, you name angular, call its module function, and give it the parameters ('theNameYouChose', ['dependencies','required'])
In the config bit there, you're telling it about dependencies config needs. $stateProvider and $urlRouterProvider are ui-router things, and $httpProvider is, I believe, an angular thing that is still necessary.
In the urlRouterProvider, you're providing the default address the website goes to: in this case it happens to be a template within a template, /signin from the signin state, and /child from the specifics pasted into signin
In the states, you are giving names and properties to the URLs that will be part of your app: like, if someone goes to index.html/signin, the 'signin' state is summoned.
The template within a template might be how you'd get the box variability that you're looking for. In box.html you will have another <div ui-view></div> and that's where the varying thing described in 'signin.child' gets put in.
box.html is also the place you put your specially created html tags, the ones you will make with the directive. I'll talk through those below.
The parent template, 'signin', talks about BoxController. Let's say you built that in box.js. It would look like this:
angular.module('yourApp.box', [])
.controller('BoxController', function ($scope) {
$scope.definedProperty = 'reRegPass',
$scope.arrayOfObjects = [{prop: 'red'},{prop: 'blue'}]
})
.directive('specificBox', function(){
return {
restrict: 'EA',
templateUrl: 'app/box/box-guts.html',
replace: true,
scope: {
source: '='
},
link: function(scope, element, attribute) {
element.on('click', function() {
alert('Functionality in specificBox is working');
}
}
}
});
The first line is again summoning angular module, and then naming it: note we already listed this, 'yourApp.box', as a requirement in app.js. Then we have the controller-naming function, and the appearance of specific properties in their $scope.
The directive is taking the more useful of the two forms a directive can take. They can either return functions (with signatures like the one in .link), or they can return objects that describe new HTML entities. This one is named specificBox, which Angular will translate into <specific-box></specific-box>. This object (technically called a 'directive definition object') can be translated into HTML tags because of the restrict property... 'E' is for element. 'A' is for attribute. I don't know how something that can be an element could also be an attribute, but having both options works, so I'm going with it. (Maybe for your various signin boxes you want a directive that has just 'A' to make new types of attributes.)
You put these specifically-crafted tags into box.html, and everything in box-guts.html will be between those tags... In fact, replacing those tags because of the replace: true.
The .link property is where you would put a function that would do something interesting to that element; turn it red if clicked, whatever. I have an alert example. Uses jQuery Lite for events.
The .scope property is odd. I believe if left off, the specific-box stuff would have the same controller as box (ie, BoxController), with box's scope and dependencies. But here, instead, we're making an isolate scope. box-guts will not depend on anything or have access to anything built before. How will it get interesting changeable data, then..? Every property in the scope object becomes an attribute on specific-box.
The '=' means that you will pass it objects from somewhere, and they will have 2-way data binding (changes made in box-guts will be reflected in the object collection in your app). Other options are '#', one-way data binding, which means you're passing box-guts a string or something that, if it changes in the DOM, you don't care to reflect in your app; or '&' to give it a function from a controller somewhere else in your app.
So ultimately, in box.html, you will have something like
<div class="box-holder">
<div ui-view></div>
<specific-box source="thing" ng-repeat="thing in arrayOfObjects"></specific-box>
</div>
Like I said above, ask questions and maybe we can sort this out.

AngularJS : How do you access ng-model's scope value within a directive that is using transclusion?

I have an application controller that is responsible for adding users to another Model. There are two ways to add users in my application. We can add them by selecting the users themselves, or by selecting an entire group which will add all of the users of that group.
To make the UI a bit more friendly, I thought it would be a good idea to have tabs for adding users individually and through groups... that way I don't have to show both forms at the same time - the user can flip between the forms using tabs.
To implement tabs, I am using Angular Directives, since I use these tabs in other places in my application. Here is the html code to show you how the tabs are implemented:
<tabs class="tabsContainer">
<tab-pane title="Users" class="users">
<form name="usersForm" ng-submit="addUsers()">
<label>Select Users Here:</label>
<select name="selectedUsers" ng-model="selectedUsers"
multiple="true" ng-multiple="true"
ng-options="user.id as user.fullName for user in users">
</select>
<button type="submit">Add Users</button>
</form>
</tab-pane>
<tab-pane title="User Groups" class="userGroups">
<form name="userGroupForm" ng-submit="addUserGroups()">
<label>Select Groups Here:</label>
<select name="selectedUserGroups" ng-model="selectedUserGroups"
multiple="true" ng-multiple="true"
ng-options="userGroup.id as userGroup.name for userGroup in userGroups">
</select>
<button type="submit">Add User Groups</button>
</form>
</tab-pane>
</tabs>
In the controller for this HTML, I'd love to get access to the tab-pane's ng-model values for selectedUsers and selectedUserGroups. I would have thought that since they are defined as transcludes, that the scope would be the application's controller itself, but I think the scope value is actually in the tab-pane directive's scope. This means that in my main application controller, $scope.selectedUsers and $scope.selectedUserGroups is not defined.
If I temporarily remove the tabs and tab-pane directives, everything in the main controller works. So I think those directives are hidding ng-model when they are transcluded within a tab-pane.
How do I get access to it?

Bind ng-models in input type checkbox

I have a problem when binding ng-models with ng-repeat in a input tag type checkbox.
I will first attach my code and then explain more in detail.
app/main.html:
<div ng-repeat="feature in features">
<input type="checkbox" ng-model="features[$index].name">{{features[$index].name}}
</div>
<br></br>
<div class="highlighter">
<span ng-class="{emo:Emotions}">Manually</span> <span ng-class="{feel:Feelings}">create</span> the <span ng-class="{emo:Emotions}">entire</span>
</div>
main.js
angular.module('webClientApp')
.controller('MainCtrl', function ($scope,$http) {
[...other variables...]
$scope.features = [{'name':'Emotions'},{'name':'Feelings'}];
[...other parts of code]
});
Let's also assume that in the main.css file there are references to the classes .emo' and.feel' respectively to highlight the target word when the user ticks the box relative to the feature.
Now, the application works correctly when I listed all the inputs one by one like the following:
<input type="checkbox" ng-model="Emotions">Emotions
<input type="checkbox" ng-model="Feelings">Feelings
but I wanted to wrap it into an ng-repeat and list the features in the controller scope, since the features I will considered will be more. When I try the code above when I tick on the box the name changes to `true'.
I have read a lot about how to bind models to an ng-repeat inside a input tag but none of the solutions apply to my case.
Can someone please help me?
I changed thigs up quite a bit from your original model but... I did get something to behave similar to what you are looking for.
HTML
<div ng-app="webClientApp">
<div ng-controller="MainCtrl">
<div ng-repeat="(feature,enabled) in features">
<input type="checkbox" ng-model="features[feature]">{{feature}}</input>
</div>
<div class="highlighter">
<span ng-class="{emo:features.Emotions}">Manually</span> <span ng-class="{feel:features.Feelings}">create</span> the <span ng-class="{emo:features.Emotions}">entire</span>
</div>
{{features}}<br>
{{features.Emotions}}<br>
{{features.Feelings}}
</div>
JS
var app = angular.module('webClientApp', []);
app.controller('MainCtrl', function($scope, $http) {
$scope.features = {Emotions: true, Feelings: true};
});
Here's the fiddle: http://jsfiddle.net/rodhartzell/8YrxQ/
Hope this helps.
(i should add this as a comment, but I don't have enough rep. yet)
There is an issue on github which concerns your issue: https://github.com/angular/angular.js/issues/1404 and the comment of caitp shows some workarounds: https://github.com/angular/angular.js/issues/1404#issuecomment-30859987
You could (also) define a new javascript object in your controller and map the elements to that.
In controller: $scope.awnsers = {};
In template: ng-model="awnsers[feature.name]"
I hope this helps
You must use ng-checked instead of ng-model.
Check out this jsfiddle
http://jsfiddle.net/fizerkhan/z5z9s/24/
ngModel and ngChecked are not meant to be used together.
ngChecked is expecting an expression, so by saying ng-checked="master". If the expression is truthy, then special attribute "checked" will be set on the element
You should be able to just use ngModel, tied to a boolean property on your model. If you want something else, then you either need to use ngTrueValue and ngFalseValue (which only support strings right now), or write your own directive.

Directive and controller communication

I'm building a filtering component for a search app and it's my first dip into AngularJS.
Here's a Plunker or what I've got so far, it works how I want it to:
http://plnkr.co/I6ewaU
There are two things which concern me with this implementation:
I have to pass filters as an attribute of the filter directive to get access to filters on the MainController, surely there must be a better way to do this? I want to modify the filters object without having to pass it as an attribute.
Is it correct to define addFilter in the filtergroup directive, or should this be defined on MainController?
I have been searching on Google for a while, but can't seem to find an alternative and would appreciate any help with this.
Cheers.
AngularJS way is to show what it does in html.
Html has to explain the functionality by not hiding it to JS.
For example, how do I know this update filters unless I read your JS? Thus, try not to make any unless it is necessary. If you make any directive, try to expose the functionality to html.
<filtergroup type="filter-name" filter-store="filters">
And there are lots of good directives in Angularjs. I always use them first.
This is how I would do it, http://plnkr.co/edit/okCp5FZJo1ZR9962uaHT?p=preview
<div class="sidebar">
<p>Filters: {{ filters }}</p>
filter1 <input type="checkbox" ng-model="filters[1]"/><br/>
filter2 <input type="checkbox" ng-model="filters[2]"/><br/>
filter3 <input type="checkbox" ng-model="filters[3]"/><br/>
filter4 <input type="checkbox" ng-model="filters[4]"/><br/>
filter5 <input type="checkbox" ng-model="filters[5]"/><br/>
</div>
"less code, less manitenance"

Categories