Optionally pass data to child element via directive - javascript

I have a popup dialog box that I wish to display one of two slightly different views, dependant on whether I have data present or not.
Is there a way in which I can optionally pass in said data within the directives?
ie. I would like to use something like
<my-comp *ngIf="ifPopup" [data]="myData" [isNew]="isNew"></my-comp>
where the [data] may not always be present, ie. It may either be undefined or have actual data present.
I just want to avoid having to basically duplicate my component.
Update after confusion around my question
Basically I am adding a new record to my DB (imagine adding a new customer etc). My component will either be used to edit a record or create a new record. If I am editing a record, myData will be filled with this record. If I am creating a new record, myData will be undefined..

why don't you just use
<my-comp *ngIf="ifPopup && myData" [data]="myData"></my-comp>
in this way, If the myData is not present, your popup wont display

Or you can also use <ng-container> and wrap your component inside and and use ngIf for your data!

Related

Preload already selected items on vue multiple-autocomplete

Let's say I have a vue-component that is able to store multiple options from a api-fetching-based autocomplete.
Looks a lot like this one but the model (which I think represents the selected entries) is an array and the v-autocomplete has the multiple option. https://vuetifyjs.com/en/components/autocompletes/#api-search
here is the codepen I edited https://codepen.io/cesarbonadio/pen/bGYLMGa?editors=1010
The problem is that I can't get it work when I try to preload already persisted data to that component.
what I currently do:
I pass the data through a prop, then I map it and assign it to the model property of the component.
The problem is that at the first instance, the selected options doesn't show up, only when I do the search inside the autocomplete, which causes the search-string to update.
if I initialize the search string as search: "", then it works, it does a search with the search-string empty, fetching all the elements that matches with "" (in other words, all of them). This is bad performance and it is not ideal because I have like 8 or 9 autocompletes inside the same parent-component.
What I can do to show up the selected options without forcing the empty search?

Can I affect properties of an Angular component based on change of other properties in a non-template-driven fashion?

I'm developing a form with Angular 6 and using some standart components, including ng-select (I'd say that's a requirement). The form is supposed to have rather complicated logic (some field values affect other values or suggestions that ng-select should show). I have a rather general question (hoping that there's an approach which I haven't just found yet), but to stay more specific, let's consider the following example:
I have 2 dictionaries (let's call them categories and items), each item being a "child" of a certain category
I have to let user select a category and an item from each dictionary, for that I have 2 fields like
<ng-select
name="category"
[items]="formSuggestions.categories$ | async"
bindLabel="name"
[(ngModel)]="formFields.category"
></ng-select>
<ng-select
name="item"
[items]="formSuggestions.items$ | async"
bindLabel="name"
[(ngModel)]="formFields.item"
></ng-select>
(in fact, they are wrapped into custom components which I omit for simplicity)
(here formSuggestions.items$ and formSuggestions.categories$ are observables that are filled with suggestions on server response; each item is actually an object having id, name and parentId)
what I need is: when a category is selected, suggestions for items are limited to those which are children of that category; when an item is selected, the category is set automatically
My question is: is there a way in Angular to "subscribe" to changes of one property in model (formFields.item) and apply it to others (formFields.category, formSuggestions.categories$) or the only way to deal with this is to set Outputs like (change) of each field?
The problem with that approach is the actual form is more complicated, for instance:
there's another interface that should be shown in a modal window, where user can choose category (and same for item), so there's multiple points which change the props
item selection should affect another ng-select's suggestions (for another field) and pre-fill some crud interface with default stuff for that item
by the way, I have to show only 10 suggestions each time (suggestion dictionaries are quite long) and there's no "limit" option in ng-select, so I have to affect suggestion list based on field value
...
so I really wonder if I can go less template-driven. Any suggestions, at least for the 2 selections case?
(change) is listening to the classical input change event (not Angular specific). See also MDN-Link
For all [(ngModel)] bound elements, you could also use (ngModelChange) to listen to changes. Thats more Angular style. And it gets even more interesting when you create your own "input" components with the ControlValueAccessor.
The problem in your example is, that you use the subscribed suggestionCategories directly. You could (theoreticly) do a "map" in the observable stream and filter out the unwanted values. But this would only work for each emited event of the observable.
So in your case i fear you have to subscribe to the source, store the result in a component local variable. You also copy the data in a second variable that you use to show the values on the UI.
And whenever the user selects a category, you take the original stored data, filter it and assign the filtered result to your second-variable.
HTML
<ng-select
name="category"
[items]="formSuggestions.categories$ | async"
bindLabel="name"
[(ngModel)]="formFields.category"
(ngModelChange)="filterCategorySugestions($selectedValue)"
></ng-select>
In Typescript you would then use the filterCategorySugestions Method to filter the data and write it into your second variable (mentioned above).
by the way, when filtering, you could afterwards apply a mylist.splice(10) (standard Array method) to limit your results to the first 10. But perhaps you should ensure the order first. :-)
I hope it helps a bit.
warm regards
Jan

How to avoid reflection of data entered in popup to the table before it is saved using Angular2

I have an edit popup, when the popup opens and i edit, it is reflecting on the table. I must avoid the reflection, once i click on save button then only the edited part must be displayed on the table. I am able to do this only for one input, i am not getting how to carry out the same way for other 2 inputs.
//Ts
editTutorial(tutorial) {
this.editTutorials.show();
this.edit_tut = tutorial;
}
You are assigning tutorial value which you sent from table into edit_tut varable, which is working as two-way binding.
so, the data in the table is getting changed along with your input.
The solution can be changing the variable reference, you can do something like,
editTutorial(tutorial) {
this.editTutorials.show();
let tut = JSON.parse(JSON.stringify(tutorial))
this.edit_tut = tut;
}
This will change the value reference and will work for you.
You have to have two different properties on your component, referencing to two different object instances. Few things to do:
Step 1: on clicking "edit", make a copy of the table row (all props) and put them inot the modal. Keep the reference to, e.g. table row you're editing, or _id or something.
In your case, add a property to TutorialComponent called currentlyEditing: any. Then, modify your editTutorial method:
editTutorial(tutorial) {
this.editTutorials.show();
this.currentlyEditting = tutorial;
}
Step 2: editing those should not reflect on the table. Go on and edit your thing.
Step 3: upon saving, sync your changes back to the table, or rather, to the original data set that's being displayed in the table. That's why you needed the reference from step 1.
Now, it's not clear to me if your edit_tut component is the one that saves changes. But if it is, I think everything will work as is. If not, you'd have to, after saving and response of "success", go and find the original tutorial in the tutorials array, and replace it with the edited component.

The template cannot be rendered by Object in vue.js

In this demo, (https://jsfiddle.net/ccforward/fa35a2cc/) I cannot render the template and the data resultWrong equals {}
In this demo, (https://jsfiddle.net/ccforward/zoo6xzck/), if I use a temporary variable to save the async data ,then I can get the result and render the template
If I add another function named as getRightData() in the methods, then the getWrongData() can work and the template can be rendered.
link: https://jsfiddle.net/ccforward/7f42owpc/4/
If I delete the getRightData() method, then the getWrongData() cannot work.
link: https://jsfiddle.net/ccforward/7f42owpc/3/
Vue cannot detect properties that are added dynamically to an object unless you add them using set.
Here is your first fiddle updated to properly add properties to an empty object using this.$set.
For your demos, the first does not work because you add the properties using an index and Vue doesn't know that it needs to update the DOM.
The second demo works because the base value, resultRight, is set to a completely different value. resultRight is a reactive value and when it changes to a different value, Vue is aware that it needs to update the DOM.
The third demo appears to work, but it only works because resultRight changes, and because it is reactive, Vue knows to update the DOM. resultWrong is rendered at the same time but only because Vue rendered it based on the change in resultRight.
The fourth demo fails for the same reason the first demo failed. resultWrong gets new properties, but Vue doesn't know about those properties. And because you are not changing the object reference (as when you change resultRight to tmp), Vue doesn't have any idea it needs to update the DOM.

valueBinding to content of array

I have this controller with a value.
App.xcontroller = SC.ArrayController.create({
...some code...
array_values = [],
..more code...
})
Now i have somewhere in a view this valueBinding
valueBinding: 'App.xController.array_values',
When I change values in the array the view does not get updated. but when i do
the following in the controller:
var array_values = this.get('array_values');
... adding / removing values to the array....
if (x_values.contains(x)){
x_values.removeObject(x)
} else {
x_values.pushObject(x);
};
this.set('array_values', array_values.copy());
the binding works, the view gets updated. But ONLY with the copy().
I don't want to make a copy of the array, IMHO this is not efficient. I just want to
let the valueBinding know content has changed..
the x values are just a bunch of integers.
The reason i want this: I want to change the value key of a SegmentedItemView. I want to change the active buttons. But I do not know on forehand how many segmentedviews I have
so I thought i bind the value of every generated segemented view to some common array and change that common array to be able to change the active buttons on all of the segmented views. Since each button represents an item with an unique key it works fine. except that i have to copy the array each time.
set the content property of the xcontroller
Bind to the arrangedObjects property of the xcontroller
You need to use KVO compliant methods on the array to get the bindings to fire. The ArrayController itself has an addObject and removeObject methods. Arrays in SC have been augmented with a pushObject method (among others), which is also KVO compliant. So if you use the KVO methods the view should update.
The reason your view does not update is because you are bound to the array, but the array itself did not change. When you do a copy, the array itself changes, so the bindings fire.
You might also want to try
this.notifyPropertyChange('x_values');
in the controller after you make the changes, but that is less preferable to using the built in KVO functionality.

Categories

Resources