What I want is when I click on a link of a component, the template will change dynamically with its subsequent state(some other html codes).
What I have done is in init process, every component's template could be displayed dynamically. When I click link Add, Invite or Accept, the property status of component was changed accordingly and function statusChanged is triggered but component's template was still not changed.
(I've spent hours on this and I'm gonna crazy.)
Here's the code on emberjs.jsbin.com:
http://emberjs.jsbin.com/laxeqigepu/2/
As the outputs, html has changed and could be logged out. But why layout is not changed?
console.log( html );
this.set('layout', Ember.Handlebars.compile(html));
Try putting these cases in your template:
//templates/components/contact-invitation.hbs
{{#if zeroStatus}}
{{#if uidPositive}}
</i> Add
{{#else}}
</i> Invite
{{/if}}
{{#else}}
{{#if wait}}
Wait
{{#else}}
...
{{/if}}
{{/if}}
//components/contact-invitation.js
import Ember from "ember";
export default Ember.Component.extend({
zeroStatus: function() {
return this.get('status') === 0;
}.property('status'),
uidPositive: function() {
return this.get('uid') > 0
}.property('uid')
//etc.
});
This is a little awkward because Handlebars lacks an {{# else if }} construct, and also because I don't know much about your domain -- my guess is there's probably a better solution than zeroStatus, oneStatus, and so on. This does seem to be the idiomatic solution in Ember/Handlebars, though: define properties in the class, and use conditionals based on those properties in the templates.
Related
I want to implement a simple copy-to-clipboard function in my Angular application.
The function to copy works, however, I do not understand how conditional statements in Angular as most of my experience is in React.
In React I would define my variable
[copy, setCopy] = useState(false)
Then, I would pass this into wherever I want to change the text or graphic element:
<button>{copy ? "click to copy" : "url copied"}</button>
Using the Angular docs, this is what my copy function looks like in Angular:
export class ThankyouComponent {
copied = false
value ='https://url.com'
}
And here is where I want to use it in my HTML file
<button [cdkCopyToClipboard]="value">{{SOME_EVENT ? "copy url" : "url copied" }}</button>
How do I access the click event of cdkCopyToClipboard in order to conditionally render the string within the button as in my React example? I've been looking around online and can't find a solution.
to display something conditionally inside an HTML template in Angular, you can use property that holds text
In HTML button attribute you can add
(click)="myOnClickMethod()"
Which calls method inside ts file whenever click event occures.
And in that method (that should belong to ts file in the same component you can do something like which changes button text to anything you want after the click.
#Component({
// Omitted for simplicity
})
export class MyComponent{
public buttonText: string = 'Copy url'
public myOnClickMethod(): void {
this.buttonText = 'Copied'
}
}
Then you can pass that variable with string interpolation to that button content like
<button ...>{{ buttonText }}</button>
Bonus
If you want to display some blocks conditionally, like some kind of fallback in case of no data, for example, in React you would probably do something like
if(!props.myList || props.myList.length < 1) return <strong>No data</strong>
return <> // some processing </>
In Angular you can use *ngIf directive
<div *ngIf="myList?.length > 0 else no-data">
// some processing
</div>
<ng-template #no-data>
<strong>No data</strong>
</ng-template>
Of course you donĀ“t need to use else statement and you can use opposite condition in other *ngIf instead.
I am taking my first steps with Vue.js and i like it very much however i met a small problem and i hope for help with solving this one.
Please check my fiddle here:
https://jsfiddle.net/eywraw8t/8410/
What i am trying to achieve is puting some buttons in relationship with others, for now, quite hardcoded, however if you click "settings on" button "setting1" and "setting2" button become visible. It works as intended but i want to root Vue instance to hold information when buttons are visible or not via this.settings = true (visible) or false (not visible). When button is created it is checked and button become visible or not depending on this.settings value.
However because i use:
template: '<div #click="kalregClicker" class="button" :class="{isNotVisible : !this.$parent[this.type]}"><slot></slot> {{ status}} {{ !this.$parent[this.type]}}</div>',
every change root's this.settings causes change of visibility of buttons and it is good. But somehow i guess that using everywhere this.$parent[this.type] is ugly. I'd prefer something like:
template: '<div #click="kalregClicker" class="button" :class="{isNotVisible : !status}"><slot></slot> {{ status }} {{ !this.$parent[this.type]}}</div>',
or
template: '<div #click="kalregClicker" class="button" :class="{isNotVisible : checkVisibility()}"><slot></slot> {{ status }} {{ !this.$parent[this.type]}}</div>',
and checkVisibilty would look like this:
function () {
this.status = this.$parent[this.type];
return this.status;
}
..but it doesnt work.
The question is: how to make updating root's this.settings to true/false to impact 's component this.status so it changes look and behaviour of component without using everywhere this.$parent[...]
I hope i made myself clear :)
Kalreg.
You should have status itself become a computed property.
Remove it from data declaration and do:
computed: {
status() { return this.$parent[this.type] == undefined ? true : this.$parent[this.type]; }
}
You can use it like:
:class="{isNotVisible : !status}"
JSFiddle here.
I have a knockout component (consists of my-template and my-viewmodel), say Component1. The template includes another component, say Component2.
<template id='my-template'>
<span data-bind='text: title'></span> //-->> this works
<div data-bind="component: {name: Component2}">
<span data-bind='text: title'></span1> // -->> this is empty
<div>
</template>
And the ViewModel:
function my-viewmodel(){
self.title = ko.observable();
$.getJSON(someUrl).then(function(result){
self.title(result);
});
}
For the first span (outside Component2), the title looks fine, but for the second span (inside Component2), the title is always empty. What is wrong in the code above? Any idea of how to fix it to make the title appears inside Component2?
I can't imagine that this is due to AJAX because the title in the first span has the value; only the second span doesn't get it. But Note that if I remove the $.getJSON, and simply assign title to some hard-coded string, and it works fine - both span(s) have the same correct value.
Is it possible that Component2 gets initialized even before the $.getJSON finishes? If so, how to make the initialization of Component2 delay until $.getJSON finishes?
======================
If you wonder why I have span inside Component2: it's just that Components2 is a tree, and the span inside it is actually some ul and li tags that Components 2 uses to render a tree.
I would like to "associate a route to a div" with Iron Router without refreshing/changing page. I'll try to be as clear as possible.
I got a div that's not displayed when you arrive in the page (ex: /home), but already exists.
When you click on something (box, text, ...), the url changes ( /home/box1) and the div appears with some data I'd have given to the route before.
But I would like to be able to do that without having to refresh the page, just to see the div appears in the same page.
So, is it possible with Iron Router and how ?
Thanks for your help.
If you are trying to display the same template on both routes, but only show the div on one of them, you can pass data into the template. The render method takes a second argument which is an object. You set the data property on that object to be a function that returns an object with all of your data values. You can then access them from the template as if they had been defined when inserting the template.
Router.route('/home', function() {
this.render('Home');
});
Router.route('/home/box1', function() {
this.render('Home', {
data: function() {
return {
showDiv: true
}
}
}
});
<head>
</head>
<body>
</body>
<template name="Main">
<p>Always showing</p>
{{#if showDiv}}
<p>Only showing when on /home/box1 route</p>
{{/if}}
</template>
Note: This will not preserve the page you are on regardless of where you are. I.E. If you wanted to do this on the /other and /other/box1 routes. If this is the behavior you're looking for I can help you with that as well.
I am developing a user profile page, which has many boxes with two modes each - view and edit. Each box is defined as a react class <ProfileBox> ... </ProfileBox>.
For the view and edit mode of each box I defined classes <EditMode> ... </EditMode> and <ViewMode>...</ViewMode>. Eventually I want to render e.g. an address like
<ProfileBox editMode={true}>
<EditMode>
...
</EditMode>
<ViewMode>
...
</ViewMode>
</ProfileBox>
I want the logic to be in the ProfileBox. My current approach is to iterate all children and filter them if they are of type ViewMode or EditMode. Too late, I realized that this breaks down as soon as I do something like:
<ProfileBox editMode={true}>
<EditMode>
...
</EditMode>
<div>
<ViewMode>
...
</ViewMode>
</div>
</ProfileBox>
How could I do it better? What is the standard approach? I don't want to have to manually care about passing an id or a status to the Edit and ViewMode in the definition of the address.
Thank you!
You can continue to render ViewMode and EditMode as children rather than pass them as props by using logic in the render function of ProfileBox similar to this:
render: function() {
var child = this.props.editMode ?
<EditMode>
...
</EditMode> :
<ViewMode>
...
</ViewMode>;
return child;
}
You can do:
<ProfileBox editMode={this.state.editingWhatever} onModeChange={this.updateEditingWhatever}
editView={ <EditMode>...</EditMode> }
viewView={ <div><ViewMode>...</ViewMode></div> }
/>
Or you can conditionally render the EditMode/ViewMode in this code. To make it less ugly, a well designed mixin would do wonders. It's hard to tell what the exact requirements are from your question, but take a look at what all of your <ProfileBox/> uses have in common, and where they differ.
In the simpler case shown above, you probably just want to dynamically create the onModeChange handler, and the onChange handler for any inputs children in edit mode.