Change from text to span in react.js - javascript

I would like the a tag to change to span when the variable 'nav' is false. When I try to do this, the text literally changes to " home " and I wish it would become an icon. What can I do?
{nav ? 'HOME' : "<span class="material-symbols-outlined"> home </span>"}

Remove " "
{nav ? 'HOME' : <span class="material-symbols-outlined"> home </span>}

Maybe move the code inside the class property and return an empty string when nav is true and material-symbols-outlined when its false.
Like this :
<span class={nav ? "" : "material-symbols-outlined"}>Home</span>

Related

changing model property value is changing the same property in other object

im new to vue , i want user to be able to add some specific social media links to the page and edit some properties like it's text
i have 2 objects in my data , models and defaults
defaults contains selectable option for social media links and their initial values
basically i copy the default value into models and let the user customize the model via inputs
data () {
return {
models : [] ,
defaults : {
twitter : { id : null , placeholder : 'my twitter' , icon : 'twitter' , text : null , 'link' : null } ,
instagram : { id : null , placeholder : 'my instagram' , icon : 'instagram' , text : null , 'link' : null } ,
tiktok : { id : null , placeholder : 'my tiktok' , icon : 'tiktok' , text : null , 'link' : null } ,
} ,
}
} ,
so there a select menu for user to select which social he wants to add to the page
Select :
<ul >
<li v-for="(social, index ) in defaults" :key="index">
<a #click="appendSocial(index)">
{{ index }}
</a>
</li>
</ul>
here is my #click="appendSocial(index)" function
appendSocial(type){
let typedefault = this.defaults[type];
this.models.push(typedefault)
},
and finally i show my models to user and provide an input for editing it's text via v-model
<div v-for="(model, index) in models" v-bind:key="model.id">
<a class="button-preview">
{{ model.text === null ? model.placeholder : model.text }}
</a>
<label>Text</label>
<input type="text" v-model="model.text" :key="index" :placeholder="model.placeholder">
</div>
so here is the problem , for some reason changing the models properties will change the same property in defaults ... and changing defaults properties will change the same property models !!
like if i add a twitter menu to the page and change it's text (model.text) to abc via v-model ... it will also change defaults.twitter.text to abc
to better demonstrate the problem i've added some console log to my appendSocialfunction
appendSocial(type){
let typedefault = this.defaults[type];
console.log(`-------- default object for ${type} -----------`);
console.log(typedefault);
this.addElement(typedefault);
},
here is the result
1 - i've selected a twitter link and added to my models , you can see defaults.twitter.text is null
2 - i've change my model.text (i suppose it would be models[0].text) to abc
3 - i've added another twitter link to my page ... this time defaults.twitter.text is also abc
also changing defaults properties will effect all the models the has been getting their value from that default object
like if i change the defaults.instagram.text to xyz all my models which have got their initial values from defaults.instagram will also change their text to xyz
it's like they are referencing each other , but i haven't passed the value between 2 objects by reference
im not sure what's happening here and how can i prevent this ?
This is because
let typedefault = this.defaults[type];
this.models.push(typedefault)
Is storing the reference to the object into your this.models array. And so if you mutate the element, you're by default changing the base object. A quick and dirty way of doing a deep clone is the following.
let typedefault = this.defaults[type];
let clonedObj = JSON.parse(JSON.stringify(typedefault));
this.models.push(clonedObj)
Note: Lodash library does have a proper deep clone functionality.
https://www.geeksforgeeks.org/lodash-_-clonedeep-method/

Class binding a ternary and non-ternary attributes

Let's say I have a tag that uses a ternary operator to add alignment to it:
<td
:class="alignment ? ('u-' + alignment) : null"
>
This works as expected since I have my pre-defined alignment classes with the number that I need, now I would like to add a new attribute in this tag, let's say I want to add the class u-bright if the prop isBright is true:
<td
:class="{'u-bright' : isBright}"
>
How to keep both conditions in the same tag? Something like:
/** Obviously this doesn't work */
<td
:class="{
alignment ? ('u-' + alignment) : null,
'u-bright' : isBright
}"
>
Try to use the array syntax :
<td
:class="[alignment ? ('u-' + alignment):'', isBright?'u-bright':'']"
>

JS Conditional Template in Column

I'm pretty new to JavaScript and it makes this even more difficult for me.
I'm trying to put a condition in my column template but I can't get it to work.
The code is this:
template: '#viewMode' == "EDIT" ? '<input class="equipDropDownEditor"/>' : "#:PROMOTION_TYPE#",
This almost shows what I want. The problem is that if the Promotion_Type field is null, it shows null on the screen.
So, the condition that I want to implement is: If the viewmode is "edit", it will return the equipDropDownEditor.
In case it is not, it shows the field PROMOTION_TYPE. But, in case that Promotion_Type returns a null, I don't want it to show anything (empty string, for example.
This is what I have tried. Still got the null on the screen when the "viewMode" is not "EDIT".
template: '#viewMode' == "EDIT" ? '<input class="equipDropDownEditor"/>' : ("#:PROMOTION_TYPE#" == null ? " " : "#:PROMOTION_TYPE#"),
To help someone in the future, I got it working with: template:
'#viewMode' == "EDIT" ? '<input class="equipDropDownEditor"/>' : ("#:PROMOTION_TYPE#" == null ? " " : "#:PROMOTION_TYPE#" == "#:PROMOTION_TYPE#"),
Thanks anyway #Bertrand Le Roy

Double false for Inline If-Else with Conditional Operator

I am trying to hide an input field if the td doesn't have a value.
I know we can have a condtition like this:
${condition ? true : false}
but how can I have an inline operator like this?
${condition ? true : false && false}
Example:
${JsonObject ? JsonObject.Description : " " && $('#textbox').removeattr("style").hide()}
The html is similar to this:
`<td>
${JsonObject ? JsonObject.Description : " " && $('#textbox').removeattr("style").hide()}
</td>
`<div><input id="textbox"></div>
If I'm understanding you right, you want the truthy result to be the description, and the falsy result to be " " and to have the side-effect of removing the style attribute from #textbox and hiding it.
I strongly recommend not doing that. Side-effects like that are extremely hard to debug and maintain.
But if you really want to, make the side-effect first:
`<td>
${JsonObject ? JsonObject.Description : $('#textbox').removeattr("style").hide() && " "}
</td>
`<div><input id="textbox"></div>
That works because hide returns the jQuery object, which is truthy, so the (object) && " " expression results in " ". Or as James Long points out, you could use the comma operator instead, and then the return value of hide wouldn't matter: ${JsonObject ? JsonObject.Description : ($('#textbox').removeattr("style").hide(), " ")} (you don't actually need those (), but it's already confusing enough, and it's even more confusing without them, so...).
But again, I wouldn't. Instead, I'd just do:
`<td>
${JsonObject ? JsonObject.Description : " "}
</td>
`<div><input id="textbox"></div>
...and then just before or just after this template literal, have
if (!JsonObject) {
$('#textbox').removeattr("style").hide();
}

Dynamic ng-class value

I've got a directive with this markup:
<button type="button" ng-class="{ 'btn-disabled': button.isDisabled }">
As you can see, btn-disabled is added as a CSS class if the scope's button.isDisabled is truthy.
Also on the scope is a property button.glyphicon. If glyphicon is truthy, I'd like to add the value of it to the <button>'s class as well.
How can I do this?
Maybe not the nicest syntax, but you could use:
data-ng-class="[button.isDisabled ? 'btn-disabled' : '', button.glyphicon]"
You could add a function to ng-class.
<button type="button" ng-class="getClass()">...
and on the controller
$scope.getClass = function(){
return ($scope.button.isDisabled ? "btn-disabled " : " ") + ($scope.button.glyphicon || "");
}
By adding this as a function you could reduce one extra watch that will be created while doing it inline in the template and abstract the logic out of html.

Categories