I want to use a JS array in Vue.js function for looping.
Tried code:
Vue:
computed: {
bbb: function(){
var vvv=this.Preused.length-this.quote.lines.length;
let added_products=[];
if(vvv > 0){
for(var i = 0; i <= vvv-1; i++){
newly_used.push({...this.Preused[this.manage.code.length+i]});
}
}
return newly_used;
}
}
HTML:
<div v-for="(cc,index) in bbb">
<p v-text="cc[index].num"></p>
</div>
newly_used:
0:
none: "calibry"
des: "Silver"
num: "numty"
By using the above code I am getting the following error;
[Vue warn]: Error in render: "TypeError: Cannot read property 'num' of undefined"
How Can I solve this?
cc.num may work, cc is single item in bbb, and you shoule check if cc exist
You're looping through newly_used properties which is returned from computed property so your v-for should be like :
<div v-for="(cc,index) in bbb" :key="index">
<p v-text="cc.num"></p>
</div>
or
<div v-for="(cc,key,index) in bbb" :key="index">
<p v-text="bbb[key].num"></p>
</div>
Related
I am having an error with if else question mark in react.
let skillSetStr = useSkillset(userInfo.Skills);
// In some cases the db returns the userInfo in different objects.
// For now this fixes the problem.
if (userInfo.Skills === undefined) {
skillSetStr = skillStr;
}
{skillSetStr ?
<div className="user-preview-info">
<div className="grid-item">Skillsets:</div>
<div className="grid-item user-preview-info_data">
{userInfo.Skills ?
<div>
{userInfo.Skills.map(
(skillName, index) => <div key={index} className="user-skill"> {skillName.skill} </div>
)}
</div>
: <div>Unspecified</div>}
</div>
</div> : ""}
So in if else condition it's suppose return "Unspecified" for in but instead it's return null.
Here is how my project look like:
How can I fix this error?
If it is saying that the array is undefined you can check it isn't empty before getting its length with "option chaining".
It would look like this:
userInfo?.Skills?.length > 0 this removes the need to do two checks.
I know it's simple example, but I'm new to Vue.
I'm sure that error is where I pointed. I'm trying to call function from computed method. There is no problem if write code straight to v:bind, but once I pass it throug func it gives me error. As well I know that from method functions call as func(), but I guess from computed they have another syntax.
<body>
<div class="container">
<hr>
<div class="sample">
<input type="text" v-bind:value="name" v-on:input="name = $event.target.value">
<hr>
<h2>Hello, {{ name }}</h2>
<input type="button" value="Click on it" v-on:click="addNumber()">
<hr>
<div v-for="num in numbers">
{{ num }}
</div>
<input type="button" v-on:click="show" v-bind:title="btnText" > //I'M SURE ERROR IS HERE
<h2 v-show="showH2">check hide</h2>
</div>
<div></div>
<script>
let sample = new Vue({
el: '.sample',
data:
{
showH2: true,
name: '12344',
numbers: []
},
methods:
{
addNumber()
{
let num = Math.floor(Math.random() * 11) - 5;
this.numbers.push(num);
}
},
computed:
{
btnText()
{
return this.showH2 ? 'Hide' : 'Show';
},
sum()
{
let sum = 0;
this.numbers.forEach((el) => sum += el);
return sum;
},
show()
{
this.showH2 = !this.showH2;
}
}
});
</script>
</body>
</html>
You are perfectly correct when you say- "There is no problem if write code straight to v:bind, but once I pass it through func it gives me error". This is because You don't call a computed and it doesn't accept any parameters. You reference a computed property just like you would a data property. Whereas a method is just a function bound to the Vue instance. It will only be evaluated when you explicitly call it. So if you shift show in methods it will work. vue doc
LONG STORY SHORT: I would like for it to load the object in the nested array IF it is not equal to undefined but react throws typeError
I have this component that takes props from a parent component. Essentially I have an array that contains chat information and when I try to access it in this child component I get some very strange behaviour.
for example if I console log(props.conversations) I get my array which looks like this: conversations[{host, members[{ username }], log[{ author, content, timestamp }]}].
if I console log (props.conversations[0]) ill get the first object in that array. But if I console log (props.conversations[0].log) I get undefined. And thats fine because at the start the state will not be defined or contain anything, so I put a ternary operator as shown below in the code props.conversations[props.index].log[0] == null ?
but all i get is TypeError: Cannot read property 'log' of undefined at the ternary function.
Maybe I am not understanding this correctly or maybe it how react functions?
Again I would like for it to load the object in the nested array IF it is not equal to undefined.
Highly appreciate the help. The most important part is the friends component. I only show the other ones to show the state being passed down.
function Friends(props) {
console.log(props.conversations[props.index]);
return (
<div className="friend">
<img className="friendavatar" src={require("./static/bobby.jpg")}></img>
<div className="friendname">{props.username}</div>
<span className="iswatchingtitle"> is watching <strong>{props.watching}</strong></span>
<div className="friendchat" onClick={props.togglechat}>
{props.conversations[props.index].log[0] == null ?
<div>undefined</div>
:
<div>defined!</div>
}
</div>
</div>
)
}
social component
function Social(props) {
return (
<div>
<div className="userquickdash row">
<div className="usernamedash">{props.username}</div>
<div className="logout"><a href="/users/logout" onClick={props.fetchlogout}>logout</a></div>
</div>
<div>
<form className="search-form-flex" method="GET" action="/search">
<input className="user-search" id="search" type="search" placeholder=" Search users..." name="usersearch"></input>
</form>
</div>
<div className='friendchatcontainer' refs='friendchatcontainer'>
{/* Append friends from social bar state (props.friends). For each friend return appropriate object info to build Friends div using Friends(props) function above. */}
{props.friends.map(function(friend, index) {
// Shortens length of video title if length of string is over 48.
let friendWatching = function friendWatchingLengthSubstring() {
if (friend.watching.length > 57) {
let friendWatching = friend.watching.substring(0, 54) + '...';
return friendWatching;
} else {
friendWatching = friend.watching;
return friendWatching;
}
};
return (
<Friends username={friend.username}
watching={friendWatching()}
key={index}
index={index}
togglechat={props.togglechat}
conversations={props.conversations}
/>
)
})}
</div>
</div>
)
}
socialbar component
class Socialbar extends Component {
constructor(props) {
super(props);
this.state = { isLoggedIn: (cookies.get('loggedIn')),
sidebarximgSrc: sidebarcloseimg,
sidebarStatus: 'open',
username: cookies.get('loggedIn'),
friends: friends,
users: {},
conversations: [],
};
}
// function to run when mongodb gets information that state has changed.
// test if the current state is equal to new object array.
// then do something.
appendFriends() {
}
componentDidMount() {
if (this.state.sidebarStatus === 'open') {
document.getElementsByClassName('maindash')[0].classList.add('maindashwide');
this.openSideBar();
} else {
document.getElementsByClassName('maindash')[0].classList.remove('maindashwide');
this.closeSideBar();
}
// check for user logged in cookie, if true fetch users.
if (this.state.isLoggedIn) {
this.fetchUsers();
}
this.getFriendConversations();
};
getFriendConversations() {
// build loop function that updates state for conversations based on length of friends array in state.
var conversationsArray = this.state.conversations;
for (var i = 0; i < friends.length; i++) {
console.log(aconversationbetweenfriends[i]);
conversationsArray.push(aconversationbetweenfriends[i]);
}
this.setState({conversations: conversationsArray});
}
render() {
let sidebar;
const isLoggedIn = this.state.isLoggedIn;
if (!isLoggedIn) {
sidebar = <Login />
} else {
sidebar = <Social username={this.state.username} friends={this.state.friends} fetchlogout={this.fetchlogout} togglechat={this.togglechat} conversations={this.state.conversations} />
}
return (
<div>
<div className="sidebar sidebar-open" ref="sidebar">
<div className="sidebarcontainer">
{sidebar}
</div>
</div>
<div className="sidebarx sidebarxopen" ref="sidebarx" onClick={this.toggleSideBar}>
<img className="sidebaropenimg" src={this.state.sidebarximgSrc} ref='sidebarximg'></img>
</div>
</div>
);
}
};
It is not a good idea to access the element directly before validation.
Use something like this:
props.conversations[props.index] && props.conversations[props.index].log[0]
Tip: User object destructuring and default props.
You need to compare for undefined like this :
{props.conversations[props.index].log[0] === undefined ?
<div>undefined</div>
:
<div>defined!</div>
}
Also, You can go to below link for sandbox running example.
Sandbox link for example to show how you should check for undefined
Hi first of all check your {props.index} print this value. if it is proper then try this out.
{
props.conversations[props.index] ?
props.conversations[props.index].log[0] ? <div>defined!</div>:<div>Undefined</div>
:
<div>Undefined</div>
}
This will check if props.conversations[props.index] is defined then and then only try to process props.conversations[props.index].log[0]. So you will not get TypeError: Cannot read property 'log' of undefined at the ternary function.
I am using jSViews and getting data back via JSON and then linking to the template.
The template shows the data I am sending it, however I have a simple post template with an array of comments.
If I try and check that the length of the array is greater than 0, using lenth, it crashed with:
0x800a138f - JavaScript runtime error: Unable to get property 'length' of undefined or null reference
here is a snippet of code:
$.getJSON("/students/dashboard/GetDashboardPosts")
.done(function (json) {
posts_data = json;
if (posts_data) {
if (posts_data.length > 0) {
var posts_html = $("#posts-template").render(posts_data);
$(".posts .row").html(posts_html);
$.templates("#post-detail-template").link(".single-post-detail .row", post_detail); // post_detail is initially an empty object
}
}
$(".post").on("click", "#posts-section", function (event) {
// get the index of the clicked item - should be able to do this with $.view but it isnt working - check it out.
var idx = $(this).closest(".dashboard-post").attr("data-index");
// update it observably so we dont have to traverse the DOM.
$.observable(post_detail).setProperty(
(posts_data[idx])
);
$("body").addClass("has-overlay");
$(".single-post-detail").addClass("expanded");
});
script id="post-detail-template" type="text/x-jsrender">
<div class="col s12 m12 l6 post">
...
...
{^{if comments.length > 0}}
{^{include comments tmpl="#post-detail-comments-template"/}}:
{{/if}}
</div>
</script>
script id="post-detail-comments-template" type="text/x-jsrender">
<section class="comments-section">
<ul class="comments-list">
{^{for #data}}
<li class="comment-item">
...
</li>
{{/for}}
</ul>
</section>
I can hack it using a helper:
{^{if ~hasLength(comments)}}
{^{include comments tmpl="#post-detail-comments-template"/}}:
{{/if}}
var viewHelpers = {
hasLength: function (arr) {
if (!arr) { return false; }
var x = arr;
if (x.length > 0) {
return true;
}
return false;
}
};
$.views.helpers(viewHelpers);
however I cant understand why it is giving me this error as ideally, I just want to include the comments template IF there are comments and not have to use an if at all, but this is the only way I can get it to work
If the post_detail has no comments property then {^{if comments.length}} will indeed produce an error. If you include a 'null check' it should work:
{^{if comments && comments.length > 0}}...{{/if}}
In WinJS can I bind a property getter in a listView? Say I have an object defined like this:
var MyLib = MyLib || {};
MyLib.ToDoItem = function() {
this.name = '';
this.description = '';
Object.defineProperty(this, "completed", {
get : function() {
return false;
}
});
}
MyLib.ToDoList = [];
//MyLib.ToDoList.push....add todo items
I am declaring a WinJS.Binding.Template where all of the properties are binding except the one that is defined with a property getter:
<div id="myItemTemplate" data-win-control="WinJS.Binding.Template">
<div class="titleTile">
<h4 class="item-title" data-win-bind="textContent: name"></h4>
<p data-win-bind="textContent: description"></p>
<div data-win-bind="textContent: completed"></div> <-- Renders as undefined
</div>
</div>
The "completed" property renders as undefined. If I put a breakpoint in the javascript console where I am loading the data, I can get to the completed property, but the databinding doesn't seem to like it...any ideas?
You missed one line after your getter.
get : function() {
return false;
}
, enumerable: true
By setting enumerable to true, you can make data binding works on this property.