I've written a custom directive to update html controls depending on a condition.
Fiddle: http://fiddle.jshell.net/agvTz/212/
The custom directive requires ngModelController, $setViewValue has updated the model value but the html control still shows no value or bunch of spaces in case of textarea. I'd imagine this has nothing to do with the digest cycle since the scope value is updated. Any and all kinda help is appreciated.
As written in the documentation, $setViewValue
does not trigger a $digest.
Therefore, you need to trigger the update via $render() method.
Related
Every once in a while I have a situation where my code changes some variable binded to the view, or even change some attribute of a Dom element, but the view renders only when all the code is executed, when I usually I don't need the effect anymore, like for example an animation for an Ajax data load.
Is there a way or a command that forces the DOM or Angular to revalidate its bindings or simple refreshes the view?
If I understand your problem correctly it looks like you need to run change detection manually.
ChangeDetectorRef.detectChanges() would trigger change detection for view and child components.
ChangeDetection Docs
I have a drop down in Angular that is a 2 way bound FORM control. When the form loads all I want to do is set a default value on the bound value so it displays that value in the drop down. When I change the value in the drop down and print to console I see the binding is correct. However the first time it loads the default value is not displayed in the drop down (not preselected) . In this sample when the form loads "cow" should be the default selected item but it is not working on page load. Please advise what is wrong in the code.
https://stackblitz.com/edit/angular-error-initial
Programmattically assign the value to your FormControl...
ngAfterViewInit(){
this.animalControl.setValue(this.animals[2]);
this.animalControl.markAsTouched();
console.log('FormControl Value: '+JSON.stringify(this.animalControl.value))
}
Stackblitz
https://stackblitz.com/edit/angular-error-initial-atr11t?embed=1&file=app/select-hint-error-example.ts
Revision
Use of ngModel with FormControl has been decprecated and is removed from Angular 7... you should start getting use to accessing values from the FormControl.
console.log('FormControl Value: '+JSON.stringify(this.animalControl.value))
https://next.angular.io/api/forms/FormControlName#use-with-ngmodel
This has been deprecated for a few reasons. First, developers have
found this pattern confusing. It seems like the actual ngModel
directive is being used, but in fact it's an input/output property
named ngModel on the reactive form directive that simply approximates
(some of) its behavior. Specifically, it allows getting/setting the
value and intercepting value events. However, some of ngModel's other
features - like delaying updates withngModelOptions or exporting the
directive - simply don't work, which has understandably caused some
confusion.
In addition, this pattern mixes template-driven and reactive forms
strategies, which we generally don't recommend because it doesn't take
advantage of the full benefits of either strategy. Setting the value
in the template violates the template-agnostic principles behind
reactive forms, whereas adding a FormControl/FormGroup layer in the
class removes the convenience of defining forms in the template.
To update your code before v7, you'll want to decide whether to stick
with reactive form directives (and get/set values using reactive forms
patterns) or switch over to template-driven directives.
I'm a bit surprised that I haven't found complete solution to this, as it seems to be a common use case:
I need help with crating custom angular directive. What I have is a form with basic front-end-side validation and messages in <span> which appear on submit.
I have simple form with validation:
jsbin sample
What I want to achieve:
Things like ng-max-length, ng-min-length, ng-pattern, ng-model etc. shouldn't be hard-coded inside of the template, rather passed as arguments from my custom-tag to the inside of directive's template - and assigned to the <input> element. (even fancier would be to assign some of the attributes to input and some other for example inside of label so that directives template can contain not only the input, but a bit bigger part of HTML, including the label)
two kinds of validation - one by highlighting the fields basing on the classes (no problem with that), second one with <span> elements appearing on submit
What problems am I facing?
How to pass the arguments (attributes) from my custom-tag to the input inside of the template?
I have now in one HTML file: formName.inputName.$error.typeOfError; How to achieve that now from the inside of the directive/template? Somehow parameterizing it.
Regarding showing validation messages on submit: Is the variable submitted set when pressing submit button and cleared when resetting the form a good idea or there is a nicer solution to that?
Make the scopes isolated so multiple instances of the directive do not interfere with each other.
Thanks in advance for help.
The docs for creating angular directives don't really give examples but what you need is the scope property defined.
Check the following:
https://jsbin.com/zabuza/edit?html,js,output
Also, be very careful with using input[number], caused me major headache in this example as it's not a normal ng type of directive.
Docs I used:
docs1
docs2
There's a bit of story behind how we ran into this... Basically, we were calling trigger('change') on all of our form inputs to let other knockout observables know their value had been reset. But I really think it's a bug in Knockout. Asking here to see if anyone else has run into it (and StackOverflow is a much nicer interface than Knockout's google forums).
So if you have a hidden input who's value is data-bound to a computed observable and you call jQuery's trigger('change') on it, it wipes out the observable. If you drill into the code, you can see that on the view model object, the member object is replaced with a string of the last value on the computed observable before you triggered the change event.
JS fiddle showing the breakage in action: http://jsfiddle.net/2VvvE/1/
It uses console.log to output the object, so be warned if you try a browser without console (cough IE). You can see that the dependent observable is working fine until you hit the 'Break It' button, after which, the value stops updating and subsequent presses output the same thing. If you comment out the line with the trigger('change') on it and re-run the fiddle, you can see that it continues to work after each button press.
Apologies for not asking a real question - we already figured a work around where we only call trigger('change') on inputs that aren't hidden (pretty straightforward jquery selector in case anyone is curious):
$("#"+this.id+" form").each(function() {
$(this).validate().resetForm();
this.reset();
// Do some actions on all the inputs, then filter before calling the trigger
$(this).find('input,select').data('valid','true').filter(':not(:hidden)').trigger('change');
$(this).find('label,legend').removeClass('validated-error');
});
But I wanted a verdict: Knockout bug? Or am I doin' it wrong?
You should not bind a normal computed observable against a read/write binding like value. This is causing it to get overwritten in your model.
If you have to you can use a writeable computed observable. In this case you could even have a blank write function: http://jsfiddle.net/rniemeyer/2VvvE/2/
The actual answer though is that you really don't need to be triggering the change events on the fields. A better way to handle this is to do it from your view model. On any observable or computed observable you can call the valueHasMutated() function to notify all subscribers again with the latest value.
myObservable.valueHasMutated()
I've used the Dirty Flag Blog post here Knockmeout to implement such a flag in my model, but i can not get this to work properly. Somehow the flag is never set to true.
Additionaly i want my subscribe event to be triggered every time the dirty flag is set to true. (i'll to the reset manually).
Here's a fiddle that shows my issue.
Can someone point me in the right direction?
A couple of small things:
when you use span tags they should not be self-closing (so do <span></span>). This was preventing your final binding from being shown.
if you create your view model inside of an object literal, then this does not yet refer to the view model, so when you created your dirty flag it was not properly tracking your Filter object. If you want to do an object literal, then you would want to create your dirty flag afterwards.
the value binding when used with a select will populate your model value with a string. So, I changed your 1 to '1', otherwise it would be dirty immediately. There is a way to force it to be numeric using a writeable computed observable. Here is one technique.
Here is an updated sample: http://jsfiddle.net/rniemeyer/xw76d/4/