I'm trying to do a search with product results using AngularJS. I've obtained an JSON object with my results": example below
[{"store_id":"17","user_id":"29","company_name":"Liquor R Us","company_type":"Alcohol",
"phone":"(303) 555-5555","website":"http:\/\/liqourrus.com","address":"5501 Peoria St",
"address_2":"","city":"Denver","state":"CO","zip":"80239","lat":"39.796181",
"lng":"-104.84863","mon_open":"","mon_close":"","tues_open":"","tues_close":"",
"wed_open":"","wed_close":"","thurs_open":"","thurs_close":"","fri_open":"","fri_close":"",
"sat_open":"","sat_close":"","sun_open":"","sun_close":"","distance":"1.1668156112981596",
"s":"s","st":"Every Store"}]
I'm using ng-repeat="store in storeResult" and the results will not display until I click on my Filter function, please note the filter is not applied!
<div class="product" ng-repeat="store in storeResult">
{{store.company_name}}
</div>
ng-click="setFilter('all');"
$scope.setFilter = function(filter) {
if(filter == 'all') {
$scope.searchProduct.product_type = '';
$scope.searchStore.company_type = '';
}
}
If I click the "setFilter" button, all results show. I'm trying to figure out how to make it display without having to click the button.
This work around only works in Chrome. Firefox and IE, never display results.
Plunker: link
My best guest is that by clicking the setFilter button you are triggering a digest cycle and your ngRepeat will be executed because of that. I suspect that you are assigning your storeResult outside the digest cycle and that's the reason is not displaying initially. I cannot tell for sure because is not in your description how is that JSON assigned to your storeAssignment .
Can you check how is that variable assigned?
Can you change the way it's and do this:
$timeout(function() {
$scope.storeAssignment = _your_json_value;
});
You will have to include the $timeout dependency but with this, a change in storeAssignment will be inside your digest cycle and the ngRepeat will see that change.
Hope that helps.
It looks like you're not setting the filter to 'all' until you click the filter function. Make sure that filter starts out as 'all'.
Related
My HTML:
<div class="check" ng-repeat="point in dbs">
<input
name="db"
id="{{point.id}}"
ng-model="point.select"
ng-click="update($index, dbs)"
ng-checked="false"
type="checkbox"
ng-required="point.select" />
</div>
Whilst my update() function looks like:
$scope.update = function(position, dbs) {
angular.forEach(dbs, function(point, index) {
if (position != index)
point.select = false;
});
}
This works as with regards to tracking what the selected checkbox is, and sending into another controller that expects the value, all is working good.
However, when I go back from the resulting page, back to this search form again, somehow the checkbox I selected before, is preselected, and I don't want anything to appear, rather just have everything blank.
Would it be as easy as simply stating:
$scope.point.select = null;
as I can't seem to find a good solution for this, so that the checkbox is always blank / not pre selected when you arrive on this form.
Let me see if I get what you are doing. It looks like you are trying to make your list of checkboxes mutually exclusive. I might look at using a radio button list (a set of radio buttons with the same name attribute, HTML interprets this as a mutually exclusive list). If you create a variable which will hold the value of the selected option and pass that value around, you probably can achieve the same result with less code. Take a look here: https://jsbin.com/sunusihuse/edit?html,js,output
As for clearing the list of controls when you revisit the page, what I have described will do that too because the value of the variable which will hold the selected value is initialized to an empty string. Hope this helps.
While working on the phone tutorial i wondered how to implement this use case
browser renders a list of phones
user clicks on add phone for one of these phones
the function addItem is fired and adds this phone into the array phonesInCart
the list with phones in cart $scope.phonesInCart = []; is updated
My codepen demo has the same logic as this code
<body ng-controller="PhoneListCtrl">
<h3>Phones we sell</h3>
<ul class="phones">
<li ng-repeat="phone in phones | filter:query | orderBy:orderProp">
<b>{{phone.name}} </b>
<button ng-click="addItem(phone)"
ng-disabled="{{phone.orderReadonly}}">add phone</button>
</li>
</ul>
<h3>Phones in your cart</h3>
<ul>
<li ng-repeat="phoneInCart in phonesInCart">
{{phoneInCart.name}}
</li>
</ul>
</body>
and relevant javascript
$scope.phonesInCart = [];
$scope.addItem = function(phone) {
// these lines have no effect on the ui
phonesInCart.push(phone);
$scope.$apply();
}
Current status
The list is rendered and the 'addItem' function is fired.
Currently the list of the phones in cart are not updated / not rendered.
My question
Could you explain
what has to be done to fill a second array phonesInCart[] and refresh another ng-repeat and
do i have to create / use more than one controller phonecatApp.controller('PhoneListCtrl' ... to be able to have a secon ng-repeat?
In your code, instead of phonesInCart.push(phone), you need to do:
$scope.phonesInCart.push(phone)
Since that is the variable you loop over in your html.
EDIT Since the addItem call happens as a part of an ng-click directive, you can get rid of $scope.$apply. Actually, you should be getting an error saying 'digest loop already in progress' with your current code.
I edited your codepen code slightly.
First off, as others already pointed out, you missed a $scope when pushing into the array of phones.
Secondly, if you want to be able to add multiple of the same phones to the list, you need to add track by $index to your ng-repeat, so it accepts "duplicates".
You also had an unnecessary $scope.apply in your addPhone function - you don't need to update it manually; when you push to the scope variable array, it triggers the digest cycle itself.
Lastly, you don't need to $watch the phonesInCart array due to the same reason as above.
Here's an updated pen to which all these changes have been made. If you have anything else to ask, please do :)
I'm attempting to highlight 1 or more items in a select box in a unit test. I'm using Karma, Jasmine, and PhantomJS, AngularJS, JQLite, CoffeeScript.
My list has items ["banana", "apple", "orange"].
I tried setting the value directly:
sourceList = element.find('select').eq(1)
sourceList.val("[banana]").triggerHandler('change');
// Or
sourceList.val("banana").triggerHandler('change');
When I get sourceList.val() it's not set.
I tried triggering events to select it. Note I can't do a "click" event because I have another event fire on click.
sourceList.find('option').eq(0).triggerHandler("active");
sourceList.find('option').eq(0).triggerHandler("focus");
sourceList.find('option').eq(0).triggerHandler("drag");
sourceList.find('option').eq(0).triggerHandler("dragLeave");
I tried using the selectedIndex
sourceList.selectedIndex = 1
None of those seem to highlight or select the item. I'm out of ideas. Has anyone accomplished this?
Here is the method of the directive which I am trying to test:
// Clicks on the add button. Should take all items highlighted and move them over
$scope.add = function(){
var sourceList = $element.find('select').eq(1);
angular.forEach(sourceList.val(), function(val, index){
$scope.selected.push({
text: val
});
});
checkListDupes();
};
This code works when I do it manually in the browser but I can't seem to get my test to highlight some items in the select box before clicking the add button. So when this code executes sourceList.val() is equal to [].
A bit late to the party, but I'll leave it here for anyone else with the same problem.
I don't know how you've built the options for the select box but sourceList.val("banana").triggerHandler('change');
should work fine as long as the value of the option is banana. If you haven't specified a track by on the ng-options, the default values that angular creates will be 'string:'+<option label> so sourceList.val('string:banana').triggerHandler('change'); should do the trick.
I have a simple Angular app which has some data, and an input box to filter that data.
<input class="form-control" ng-model="filters.generic" />
<h3>{{filteredUsers.length}} filtered users</h3>
<ul>
<li ng-repeat="user in filteredUsers = (data.userData | filter:filters.generic )">
{{user.registration.firstName}}
</li>
</ul>
The 'filteredUsers' variable stores the users with the applied filter. That all works absolutely fine. However, I'd like to be able to add a watch to execute a particular function whenever this 'filteredUsers' variable changes (whenever the user types anything in the input box).
I do not want to simply add a method to ng-change on the input, because I want to introduce other filters elsewhere.
I thought that I could do this in my controller with
$scope.$watch('filteredUsers', function () {
alert('something');
});
This executes once, when the application loads, and then never again. What must I do to make this watch for changes to filteredUsers?
You might need to use $watchCollection() instead of $watch()
Keep in mind that the filter on an ng-repeat could be running way more frequently than you need or expect it to, and adversely affect the performance of your code.
Even though you said you don't want to use ng-change, I think you should reconsider that and only update your array when needed.
<input class="form-control" ng-model="filters.generic" ng-change="genericFilterChange()" />
var updateFilteredUsers = function(){
$scope.filteredUsers = $filter('filter')($scope.data.userData, $scope.filters.generic);
alert('something');
};
var genericFilterChange = function(){
updateFilteredUsers();
updateOtherFilteredThings();
};
I'm using ng-show to show a div upon clicking a button.
The div I'm ng-show-ing contains a course schedule with dynamically updated courses as the user clicks around and adds courses.
But when this course schedule gets triggered to show, it is in a stale state. There are no courses appearing.
Any insight onto why all the added courses data is not actually showing? Is there something special that has to be done after ng-show to refresh the state of the data?
HTML:
<div id="schedule-div" ui-calendar="uiConfig.calendar" ng-model="eventSources" ng-show="scheduleMode" calendar="weekView"></div>
JS:
// Event handle for "Generate Schedule" button
$scope.getSchedules = function () {
scheduleFactory.getSchedules($rootScope.addedCourses).
success(function (data) {
var scheduleListing = angular.fromJson(data);
// Create closure with current scheduleListing
scheduleInstance = renderSchedule(scheduleListing);
scheduleInstance(0);
// $scope.events is the data used
// This log correctly, logs data
console.log($scope.events);
// Toggle the ng-show
$scope.scheduleMode = true;
}).
error(function() {
$window.alert("Schedules not found.");
});
};
As you can see this is all happening in a callback from the server (I don't think this should matter though). The console.log() shows the data correctly so the data does exist by the time the ng-show is toggled.
When the ng-show logic is completely removed the data is correctly updated in the schedule view. So the problem must lie somewhere in ng-show displaying a stale state.
Check your data source. ng-show doesn't care about the content. It just make the container display:none or display:block based on the condition.
Your datasource is not getting updated.
If you have any example than post.
after code
// Toggle the ng-show
$scope.scheduleMode = true;
add
$scope.apply()
You're using ng-model=eventSources to set your data in the schedule listing. It doesn't appear to be updated, as the variable eventSources isn't being used in your getSchedules() code. That controls what get's updated inside the div.
ng-show only shows or hides the div, doesn't control anything else inside of it.