Angular: ng-show stale state - javascript

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.

Related

Dynamically loaded JS needs to be clickable just like it's in the html

My page fires off an ajax query, where the MySQL Db is queried and the results are returned. (all successful).
Those results are formatted for output as a shopping gallery/catalogue and also as an accordion filter menu. So I can filter the shopping catalogue display. eg say I want to see only items that are red.
All is working so far.
My problem is with the filter accordion menu - dynamically created in js.
When I click on any selectable item in the tab-content, nothing happens. This means the parameter that should be sent, isn't being sent.
If I hard code the accordion filter or even load it with my server-side language, into the html directly, the filtering does send off the parameter and so the shopping catalogue is adjusted accordingly but, in that scenario, I am unable to dynamically change the filter menu.
I think the code I shall post below is the relevant code that recognises changes in the originally loaded content and fires off the ajax but (I think) it doesn't understand any changes to textboxes in the dynamically loaded content.
Please help me to understand what I need to add that will make dynamically loaded content fire-off to the ajax calls.
var $checkboxes = $("input:checkbox");
function update_nav_filter(opts) {
$.ajax({
type: "POST",
url: "/php-queries/product-filter-query.php",
dataType: 'json',
cache: false,
data: {
filterOpts: opts
},
success: function(records) {
//console.log(records);
//alert('SUCCESS!');
// alert(records);
$('#filters_div').html(makeFilter(records));
}
});
}
$checkboxes.on("change", function() {
//alert('there is a change is checkbox status'); // working on page load but not when any checkbox is clicked-on
var opts = getCatalogueFilterOptions();
updateCatalogue(opts);
update_nav_filter(opts);
});
$checkboxes.trigger("change");
Any help greatly appreciated.
I have created an event listener.
Following page-load, I select an item in the JS generated nav filter. eg pedal_bins in the sub_category section. I am then shown a display of pedal_bins. :)
Then I select 'kettles', another sub_category but I can only see the last sub_category that I click on. The pedal_bins disappear.
How best can I build and remove items with a single click? Store in a session parameter and then
a. remove the latest click if it matches whats in the session
b. add the latest click if its not already in the session
Then submit whatever the array is at that stage?
Or, is there a better way to run this?
Here's the listeneer
enter code here
document.getElementById("filtering_div").addEventListener("click",function(e) {
// e.target was the clicked element
if (e.target && e.target.matches("input")) {
var parameter = e.target.id;
//console.log("Anchor element", parameter , " was clicked" );
var opts = getCatalogueFilterOptions(parameter);
console.log(opts);
// update_nav_filter(opts);
updateCatalogue(opts);
}
});
You have a "delegation" problem. When you create a dynamic element, in order to be able to act on the newly created element, you have to reference it as a child element that was originally loaded with the DOM.
For example, if you have an element called <div id="top"></div> and you create a dynamic element, let's say <button id="test">Click</button> in there, you'll have to refer to that div when adding an event listener.
$("#top").on('click', '#test', function(){
//event related code goes here.
});
Here is a fiddle I created that explains the whole thing with some examples.
If you have any questions about it, please let me know.

ng-class is not being updated

cy.on('tap', 'edge,:selected', function (event) {
$scope.$apply(function (response) {
$scope.dataToDisplay = {
data1:true
}
});
});
I have the following code above. It is an event that fires as any edge is clicked/tapped on in a Cytoscape.js graph.
I am able to display the $scope object utilizing $scope.$apply. In the html, I also have an ng-class directive that will display accordingly whether it's true/false. However, the ng-class does not seem to respond as the value changes.
Below is a snippet of the ng-class directive,
<div ng-if="dataToDisplay">
<div class="panel" ng-class="{'panel-danger': dataToDisplay.data1, 'panel-default': !dataToDisplay.data1}">
<div>
</div>
Assistance is much appreciated.
I would like to clarify that the class does get updated as the page loads. However, I have an additional ng-click event that toggles the true/false. This does not add/remove the class as the value change but the value does get updated in the view. How can I achieve update the class as the value changes?

ng-show expression not updating after variable update

I have a controller which prints some data in a ul using a ng-repeat. Each li is divided in two parts:
<li>
<div>
<button type="button" class="some classes" ng-show="!field.edit.state" ng-click="field.edit.update(true)">Edit</button>
<button type="button" class="some classes" ng-show="field.edit.state" ng-click="field.edit.update(false)">Save</button>
{{field.title}}
</div>
<div ng-show="field.edit.state">
<input />
</div>
The idea is, when the "Edit" button is clicked the input field and the "Save" button are shown, while the "Edit" button itself is hidden. Clicking on the "Save" button goes on the other way around. Since I need to execute some functions on the start and the end of the editing the update also triggers some callbacks from my controller. Now, the callbacks are correcly triggered, the state is updated, but nothing changes on my page.
The update function code is pretty simple:
function registerEdit(callback){
var state = false;
var update = function(newState){
state = newState;
callback(newState)
$timeout(function(){
$scope.$apply()
})
}
return {
state : state,
update : update
}
}
Each field element is injected its own registerEdit property when the data are fetched from the server and injected in the $scope, so they are unique (I've checked that part, and it works). From what I know about Angular, after changing the $scope all I needed to do was to call the $apply function to have Angular change my view, but even as the state changes (I logged it) the display remains the same.

How to display angularjs ng-repeat with json object

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'.

Updating AngularJS models on ng-click, DOM not responding

I have an input box and a textarea that are held inside a modal window that is open upon a button-click. The same input box and textarea are in use by a second modal with a different purpose. Each modal is under a different controller. So when I click on the button for the first controller, I want certain changes to apply to the modal as opposed to when I click on the other controller's button.
However, since these controllers share these input and textarea fields, sometimes information from one and the other pass to each other due to the ng-models within them. Other times, if I open a modal window, type into the inputs, close it, and then reopen the same window, the content still remains in the input fields.
This is all because I can't figure out how to update the content of these input/textarea fields from within my controllers. I'm not sure what I'm doing wrong. My models are not updating the DOM--help?
ControllerA, for new posts:
$scope.anonOrName = "anonymous"; //value when user posts anonymously
$scope.systemUserName="name from system here"; //value when user posts not-anon
//New title defined by the user for the post.
$scope.title="";
//post content the user fills in
$scope.postContent = "";
/*
* Operates the New Post modal window, calling functions from the modalManager
*factory
*/
$scope.newIdeaClick = function() {
$scope.title=""; //make sure title input is blank, doesn't work
$scope.postContent=""; //make sure the textbox is blank, doesn't work
document.getElementById('title').disabled = false; //allows user to type a new title, sometimes doesn't work
document.getElementById('anonymous').disabled = true; //user must post anonymously
modalManager.open('newPost'); //open the modal window
};
ControllerB, for new comments:
$scope.anonOrName = "anonymous";
$scope.systemUserName="name from system here";
//Title of the post the user is commenting on. The user cannot change this.
$scope.title="";
// Content of the textarea, the new comment written by the user.
$scope.postContent = "";
/*
* Operates the New comment modal window, calling functions from the modalManager factory
*/
$scope.newCommentClick = function() {
$scope.title="(some title will go here"; //sets the title, cannot be changed, doesn't work
$scope.postContent=""; //make sure the textbox is blank, doesn't work
document.getElementById('anonymous').disabled = false; //user can select anon or not
document.getElementById('title').disabled = true; //user may not choose new title
modalManager.open('newComment');
};
index.html has two calls of the following code, one under ControllerA, the other under ControllerB:
<modal>
<input ng-model="title" class="titleInputBox" id="title" />
<div class="commentPostName">
<div class="nameBlank">
{{anonOrName}}
</div>
<label>
Anonymous:
<input type="checkbox" ng-model="anonOrName" class="anonCheckBox" ng-true-value="anonymous" ng-false-value="{{systemUserName}}" id="anonymous" />
</label>
</div>
<textarea id="postBodyTextArea" ng-model="postContent">
</textarea>
</modal>
title and postContent are my two models I'm trying to set blank upon each time the respective post or comment button is clicked, calling the click functions defined in each controller. But they won't update the blanks in DOM.
Any help would be greatly appreciated!
Update: Through debug statements I've been able to determine that the values themselves have been reset to blank like I've written code for, but the change simply doesn't respect on the DOM. I've also tried to use $scope.$watch on these models to do the same thing, but no luck.
Update:
The selected answer worked, but I had various other bugs in my code that kept the correct answer from acting as if it had any effect. But it's working now! Just not with the above code.
The issue might be caused by scope inheritance. Instead of doing $scope.title, $scope.postContent you should store the string values inside an object as a property.
$scope.models = {
title : "",
postContent: ""
};
in markup
<input ng-model="models.title" class="titleInputBox" id="title" />
<textarea id="postBodyTextArea" ng-model="models.postContent">
The direct controller of the modal is likely not the controller you've written, instead a child of your controller. For details on this, please read Understanding Scopes, you will probably benefit from it as it is a common task.

Categories