In my application I have used calendar widget using fullcalender.js:
$(document).ready(function() {
$('#profile-calendar').fullCalendar({
events: $scope.calendarEvent
});
});
What I wanted to do is, I need to give different values to the event attribute based a angular event. the below code snippet is what I have used to update the $scope.calendarEvent attribute.
$scope.$on('profile_selection',function(event, args){
$scope.calendarEvent = $rootScope.calendarEvent;
$scope.$apply();
});
But this is not working as I expected, the calendar is showing the initial value given to the $scope.calendarEvent. What should I do to make the $scope.calendarEvent take the changed value by the broadcast message and update dynamically.
Related
I have a customer who is a member of a web site. He has to fill a form every time which is really very often. That's why he wants me to develop an application for him to make this process automatic. When I use the webBrowser control to manipulate it, I am able to login but after that there are fields that contains data-binding. These fields are the ones I need to manipulate. When I push the data to necessary fields, it's not working, because in the html tag, there is no value attribute, instead it has data-binding. So my question is how can I manipulate and push data to these fields?
Thank you so much for your all help in advance.
Knockout uses data-binds to listen to changes in an input and update an underlying model. For example, the value binding listens to change events and writes the new value to a data-bound observable.
If you update a value attribute through code, the change event isn't triggered. You'll see the new value in the UI, but the javascript model won't be updated.
You can combat this by explicitly triggering a change. Here's an example:
Type in the input: you'll see a console.log that shows knockout gets updated
Press the button to inject a new value: you won't see a log: knockout isn't updated
Press the last button to trigger a change event. You'll notice knockout now updates the model.
Of course, you can combine the two click listeners into one function. I've separated them to get the point across.
// Hidden knockout code:
(function() {
var label = ko.observable("test");
label.subscribe(console.log.bind(console));
ko.applyBindings({ label: label });
}());
// Your code
var buttons = document.querySelectorAll("button");
var input = document.querySelector("input");
buttons[0].addEventListener("click", function() {
input.value = "generated value";
});
buttons[1].addEventListener("click", function() {
// http://stackoverflow.com/a/2856602/3297291
var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", false, true);
input.dispatchEvent(evt);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<input type="text" data-bind="value: label">
<button>inject value from outside</button>
<button>let knockout know something changed</button>
I'm stuck on this issue: I'm trying to limit the number of selections a user can make from an available dropdown selection list. The list is drawn from a database, so its not a hard-coded option list. I'm currently using angularMultipleSelect, its works fine expect for this requirement.
If the user exceeds the maximum selections, I want to set the field to invalid, so that the user cannot save the form. The user should then remove one or more of the selections, until the valid selections are made, then the field should reset to valid. I've tried using:
after-select-item (a directive available with angularMultipleSelect)
ng-change
custom validation directive
None of these work. I can get ng-change & custom validation directive to work on other input fields in the same form, but not on the 'multiple-autocomplete' tag. Nothing is triggered when the user makes selections from the dropdown list.
Here is a simple sample of the code used with after-select-item method. I'm trying to limit the user to 3 or less selections from the available options in the 'cats' array.
HTML:
<multiple-autocomplete
ng-model="selectedCats"
name="selectedCats"
object-property="name"
after-select-item="afterSelectItem"
required
suggestions-arr="cats">
</multiple-autocomplete>
Controller.js:
$scope.afterSelectItem = function(selectedCats) {
var catLength = $scope.selectedCats.length;
var valid = (catLength <= 3);
$scope.myStoryForm.selectedCats.$setValidity("maxLength", valid);
};
Again, nothing gets triggered in this controller when selections are been made (checked at console).
Is there something I'm not doing right, or is there another approach I could use to meet this requirement?
Thanks.
You could try using $watch to watch for changes in your model.
E.g.
$scope.$watch("selectedCats", function (newValue, oldValue) {
var catLength = newValue.length;
var valid = (catLength <= 3);
$scope.myStoryForm.selectedCats.$setValidity("maxLength", valid);
});
This gets triggered every time that your "selectedCats" value changes as well as the first time that you initialise the value.
I am trying to to update/change the highlighted days in callendar view. But they are not updated on next event when calendar is shown.
There is working Plunker snippet: https://plnkr.co/edit/4HkCp5?p=preview
Part of code:
var element = $("#datetimepicker");
//element.datetimepicker('destroy');
element.datetimepicker({
'setOptions': {
highlightedDates: ["08/10/2016,,xdsoft_highlighted_mint", "10/10/2016,,xdsoft_highlighted_mint"]
}
});
How can I make that the highlights were updated after setting the new value to "highlightedDates"?
Some realated questions:
xdan/datetimepicker using knockout - can not update “highlihted days” dynamicaly
Note: I can not use "element.datetimepicker('destroy')" because it will destroy all data and I only need to update highlights.
Found solution...
So problem is that when new value of highlightedDays is empty array, then the "highlightedDays" value is not updated. So you need always some dummy value to update previous value.
This is like a hack, but works. I am passing dummy date from 1970`th, so no one cares about it...
I am developing an app that works with a "Widget layout".
The user gets a page which is a Dashboard with different widgets he can interact with, such as a table, graphs etc.
I am adding a global "filter" using <md-chips>, the objective of this is having filters that are shared by all the widgets and can be updated by all the widgets.
My Filter list uses <md-chips>, with read-only and md-removable set to True. So filters can only be deleted, or added by interacting with the widgets (so only added programmatically).
One of the feature of this "module" is to add a new filter on a field when a Graph element is clicked.
Example :
Here is my Filters list before clicking a Graph element
Now I click on a Graph element which is in a Child controller of my Filter controller, it will $emit an event to say to the global controller : "I want to update the filters ! here is the filter to add"
And the Filter Controller will get that event and update his filters accordingly ($scope.tags is the list of filters and the model used in <md-chips>)
// CHIPS
$scope.tags = [];
$scope.readOnly = true;
$scope.removable = true;
// FILTER LISTENER
$scope.$on('filterChildChanged', function (event, filter) {
$scope.tags.push(filter);
console.log($scope.tags);
console.log("Parent event fired !");
});
At that point I would expect the <md-chips>element to refresh, because $scope.tags just got a new filter :
<md-chips
ng-model="tags"
readonly="readOnly"
md-removable="removable"
id="filters">
<md-chip-template>{{$chip.value}}</md-chip-template>
</md-chips>
But instead, nothing happens! and the weird part is, it refreshes when I click on one of the existing chip (I had a "test" chip) !
TESTS :
So when I push a test chip on the array before rendering :
$scope.tags.push({field: "testField", value: "test"});
And click on a bunch of Graph elements, $scope.tags is perfectly updated, BUT the visual stays the same until I select the chip "test", then all the <md-chips> appear just like it triggered some refresh function.
Any hint on why the <md-chips> element is not refreshed as $scope.tags (its model) is updated BUT is updated when a chip is selected ?
I tried to trigger md-on-select to force this behavior to happen every time I add a new filter to $scope.tags but I got no luck so far !
Thanks for reading !
NOTE : I am using the latest version of Angular MATERIAL (HEAD MASTER) see doc here : https://material.angularjs.org/HEAD/ | built from the GitHub repository.
EDIT : The problem comes from $$hashKey not being added to the objects, they are only added when I click on one of the existing tags, I need to find a way to add this $$hashKey attribute when I add a new filter
The problem came from the absence of $$hashKey when I added a new filter to my filters model for my chips ($scope.tags).
So I just needed to change
$scope.tags.push(filter);
to
$scope.$apply(function () {
$scope.tags.push(filter);
});
And here is my console.log test
Good thing I learned :
the <md-chips> directive only knows it needs to be updated if its <chip> objects have a $$hashKey
See this on scope.$apply
I believe this question is similar to this one but as far as could see in the rules, if there is no answer and it is not the same scenario, I'm allowed to ask.
I've simplified my real scenario with the following, basically, the checkbox is getting checked through some unaccessible code which doesn't get the view model of knockout.js to detect. Is there a work around?
HMTL:
<input id="myCheckbox" type="checkbox" data-bind="checked: myValue" />
<div data-bind="text: myValue"></div>
javascript:
var viewModel = {
myValue: ko.observable(false)
};
ko.applyBindings(viewModel);
setTimeout(function() {
$("#myCheckbox").attr("checked", "checked");
}, 1000);
When a checkbox is modified using the setAttribute function or the checked property, as jqGrid does, it doesn't trigger the click event that Knockout's checked binding uses; neither does it trigger a change event. To be able to detect these changes, you have different options depending on the browser/version: MutationObserver, DOMAttrModified, and/or onpropertychange.
But I'd suggest avoiding those solutions and using what jqGrid gives you: either the jqGridSelectRow event or the onSelectRow callback. You might want to check out the Knockout-jqGridBinding plugin that should give you a good starting point. It includes a selectedItems option that lets you bind an observable array to jqGrid's selected items (using the onSelectRow callback internally).
EDIT:
To re-iterate, I suggest you don't try to solve the problem by watching the checkboxes. But if that's the way you want to go, there's a jQuery plugin, attrchange that provides cross-browser support for this.
Resources:
Knockout-jqGridBinding: https://github.com/CraigCav/Knockout-jqGridBinding
attrchange: http://meetselva.github.io/attrchange/
The answer to which you linked explained that Knockout needs to be alerted of the change through a usual event, such as "click". Here is the idea posted there by Rustam:
function update(){
var $cb = $(':checkbox');
var cb = $cb[0];
// change value directly on element
cb.checked = !cb.checked;
// propagate changes to KO
$cb.triggerHandler('click');
}
setTimeout(update, 1000);
Of course the method more native to KO would be to change the observable on the model, like so:
var update = function() {
viewModel.myValue(!viewModel.myValue)
};
I was not able to fix this on my code in which Foundation was taking control of the checkbox. I ended up binding a click event which then checked on the checkbox to see if it was checked (we only had 1 checkbox that we were trying to keep track of). I then updated the observable from that click event based on whether it was checked or not.
No way around this that I know of.