Here’s my code
<form>
<div v-for="(inputAvion, index) in inputsAvion" :key="inputAvion.id" :id="`avion-${index}`">
<input placeholder="origin" name="data" />
<input placeholder="destination" />
<div class="ui button small green" #click="addAvion">+</div>
<div
class="ui button small red"
#click="removeAvion(inputAvion)"
v-show="inputsAvion.length > 1"
>
-
</div>
{{ index }}
</div>
</form>
And the script part :
<script>
export default {
mounted() {
this.inputsAvion.push(this.inputsAvion.length + 1);
//this.inputsAvion.push(this.inputsAvion);
},
data() {
return {
inputsAvion: [],
};
},
methods: {
addAvion() {
this.inputsAvion.push(this.inputsAvion.length + 1);
},
removeAvion(index) {
this.inputsAvion.splice(index, 1);
console.log(this.inputsAvion)
console.log(index)
}
},
};
I would like to add the div element each time the button “+” is clicked and assign a unique id to the div (I willl then add autocomplete google map places to calculate distance between 2 locations)
I think I did it correctly … hope so ^^
But I’d like to use also a remove button to delete the selected line. I’ve tried a lot of things but only managed to remove the last “div” added not the one I clicked.
If someone could help me I’d be grateful a lot ! :)
Thanks
You should pass the index instead of inputAvion
#click="removeAvion(index)"
then
removeAvion(index) {
this.inputsAvion.splice(index, 1);
...
I need some help about the code: I have to make a filter for a list of objects and I have to use the observables (the exercise only includes the front end part) and the objects are in a database.
with the code written as soon as I insert a letter in the search bar, the array is emptied and only the last letter remains (for example insert C and after I insert E, in the filter only the E remains)
in TS:
Search(name:any):void{
this.arraycopy=this.mylist
})
this.arraycopy=this.mylist.filter(res =>{
return res.description.includes(name.key) ;
})
}
IN HTML:
<div class="row">
<div class="col-2" *ngFor="let object of arraycopy">
<div class="card">
<div class="card-block">
<p class="card-text">
<a class="breadcrumbLabelStyle" href="{{list.listCode}}" title="access to {{list.description}}">{{list.description}}
</a>
</p>
</div>
</div>
</div>
</div>
Are you sure you're updating your Observable with the full search-bar input and not just the last key pressed?
You are probably updating it based on the keypress event which returns the last key pressed.
Update on Answer:
Try this:
Search-bar:
<input type="text" [ngModel]="searchInput" (keyup)="Search()">
In TS:
public searchTerm = new BehaviorSubject('');
public searchInput: string;
constructor() {
this.searchTerm.subscribe((text: string) => {
this.arraycopy = this.mylist.filter(res => {
return res.description.includes(text);
});
});
}
public Search(): void {
this.searchTerm.next(this.searchInput);
}
This should work, but with this you're not using Observables so good.
I made a simple application (in react js) that has two lists and you can add elements to that list. One is a list of input elements and other is list of spans.
Upon adding new element, the list of span renders perfectly but the list of inputs renders differently.
This is how my react class looks like
var App = React.createClass({
getInitialState: function(){
return {
'app': {
'data': this.props.data,
'data2': this.props.data2
}
};
},
onclick: function(){
var dat = this.state.app.data;
var val = this.refs.input.getDOMNode().value;
dat.splice(0, 0, val);
var dat2 = this.state.app.data2;
dat2.splice(0, 0, val);
this.setState({'app': {
'data': dat,
'data2': dat2
}});
},
renderElement: function(i){
return(
<input defaultValue={i} />
);
},
renderElement2: function(i){
return(
<span>{i}</span>
);
},
render: function(){
var self = this;
return(
<div>
<input type="text" ref="input" placeholder="Enter a value"/>
<input type="button" value="Add value" onClick={this.onclick} />
<div className="col2">
{this.state.app.data.map(function(page, i){
return(
<div key={i}>{self.renderElement(page)}</div>
);
})}
</div>
<div className="col2">
{this.state.app.data2.map(function(page, i){
return(
<div key={i}>{self.renderElement2(page)}</div>
);
})}
</div>
</div>
);
}
});
This is how the App is rendered
var data = [1,2,3];
var data2 = [1,2,3];
React.render(<App data={data} data2={data2}/>, document.getElementById("main"));
Here is the DEMO
My test case:
I add 55 and expect the results to look like this
55
1
2
3
55
1
2
3
But I get
1
2
3
3
55
1
2
3
Am I missing something basic here ?
First render looks (roughly) like this:
<div>
<div key={0}><input defaultValue="1" /></div>
<div key={1}><input defaultValue="2" /></div>
<div key={2}><input defaultValue="3" /></div>
</div>
<div>
<div key={0}><span>1</span></div>
<div key={1}><span>2</span></div>
<div key={2}><span>3</span></div>
</div>
Cool, no problems. Then let's say I put 'foo' in the box and click Add Value. The state updates by inserting it before the first item (side note: splice(0,0,x) is unshift(x)), you then render this:
<div>
<div key={0}><input defaultValue="foo" /></div>
<div key={1}><input defaultValue="1" /></div>
<div key={2}><input defaultValue="2" /></div>
<div key={3}><input defaultValue="3" /></div>
</div>
<div>
<div key={0}><span>foo</span></div>
<div key={1}><span>1</span></div>
<div key={2}><span>2</span></div>
<div key={3}><span>3</span></div>
</div>
Now it's time for React to take these two, and figure out what changed. To do this it compares the component (div, span, or input here), and the keys.
Starting with the span section, it sees that all the tags are the same, but there's a new key it hasn't seen before at the end. It also sees that the value of div[0] span, div[1] span, and div[2] span have all changed. It inserts the new elements with the text 3 at the end, and updates the other spans. Inefficient, but it works.
Now for the inputs... it does roughly the same thing. The keys and tags for the first three inputs are the same, it tells each of the inputs that they're updating, they check if they have a value prop, and if not, kindly deny to do anything.
It sees that there's a new input at the end. It is at div[3] input and has a defaultValue of "3". React inserts the new input, sets the value to 3, and the update is complete.
As you continue, the above procedure is the same, and it continues updating the spans, and inserting a new div span and div input each time.
The main problem here, aside from defaultValue which I don't think should ever be used, is the keys are upside down! Items are being inserted at the beginning, so keys should descend, not ascend. This can be fixed by using the length of the items and subtracting the index from that. If length is 4, the keys will be 4, 3, 2, 1.
this.state.app.data.map(function(page, i, items){
return(
<div key={items.length - i}>{self.renderElement(page)}</div>
);
})
React then says 'oh, there's a new item at the beginning, I should just insert a node there', and everyone's happy. The end.
Sorry, I don't know the exact reason why this is happening, but if you include a value for the key attribute on your inputs, it resolves the issue:
renderElement: function(i){
return(
<input key={i} defaultValue={i} />
);
},
My guess is that the lack of 'key' and use of 'defaultValue', instead of 'value', makes it difficult for React to correctly diff the change.
I have an ng-repeat that is outputting a number of <p>. I would like to truncate the text and add a read more button that expands when you click it.
This is what I have so far:
//NG-repeat
<div class="col-xs-4 mbm" ng-repeat="wine in wines">
<p readMore> {{wine.copy|truncate: textLength }}
<a ng-click="changeLength()" class="color3"><strong>More</strong></a>
</p>
</div>
//NG-click
$scope.changeLength = function() {
$scope.textLength = 9999;
}
I have a custom directive that is able to truncate the length of the string. But when trying trying to modify the text length via and ng-click I am finding all the of items in the ng-repeat are modified.
Is there a way to change a single ng-repeat item?
Target the wine for the ng-click:
<p readMore> {{wine.copy|truncate: wine.textLength }}
<a ng-click="changeLength(wine)" class="color3"><strong>More</strong></a>
</p>
And then only truncate the targeted text:
$scope.changeLength = function(wine) {
wine.textLength = 9999;
}
I started using Firebase (AngularFire) for synchronizing my data for my application. It's a Card tool for Scrum that adds cards to an array. You can manipulate the input fields.
In the first place I used localStorage, which worked really well. Now that I basically implemented Firebase, I got the following problem: After typing a single key into one field, the application stops and the only way of resuming typing is to click in the input field again.
Do you know why this is? Thank you very much in advance!
That's my basic implementation in my Controller:
Card = (#color, #customer, #points, #number, #projectName, #story) ->
$scope.cards = []
reference = new Firebase("https://MYACCOUNT.firebaseio.com/list")
angularFire(reference, $scope, "cards")
$scope.reset = ->
$scope.cards = []
$scope.addCardRed = (customer) ->
$scope.cards.push new Card("red", customer)
That's my Markup:
<div class="card card-{{ card.color }}">
<header>
<input class="points" contenteditable ng-model="card.points"></input>
<input class="number" placeholder="#" contenteditable ng-model="card.number"></input>
<input class="customerName" contenteditable ng-model="card.customer.name"></input>
<input class="projectName" placeholder="Projekt" contenteditable ng-model="card.projectName"></input>
</header>
<article>
<input class="task" placeholder="Titel" contenteditable ng-model="card.task"></input>
<textarea class="story" placeholder="Story" contenteditable ng-model="card.story"></textarea>
</article>
<footer>
<div class="divisions">
<p class="division"></p>
<button ng-click="deleteCard()" class="delete">X</button>
</div>
</footer>
</div>
<div class="card card-{{ card.color }} backside">
<article>
<h2 class="requirement">Requirements</h2>
<textarea class="requirements" placeholder="Aspects" contenteditable ng-model="card.requirements"></textarea>
</article>
</div>
I ran into this as well. This is because it's recalculating the entire array. Here's how I fixed it:
Bind your input to an ng-model and also add this focus directive
<input class="list-group-item" type="text" ng-model="device.name" ng-change="update(device, $index)" ng-click="update(device, $index)" ng-repeat='device in devices' focus="{{$index == selectedDevice.index}}" />
I set the selectedDevice like this
$scope.update = function(device, index) {
$scope.selectedDevice = device
$scope.selectedDevice.index = index
}
Now create this directive.
angular.module('eio').directive("focus", function() {
return function(scope, element, attrs) {
return attrs.$observe("focus", function(newValue) {
return newValue === "true" && element[0].focus();
});
};
});
Update Sorry for the delay, had a few things to tend to.
The reason why this works is because it is constantly saving the index value of the item in the array you are currently selecting. Once focus is lost, focus is returned immediately by going to that index.
If we're talking about multiple arrays, however, you'll need to refactor the setSelected code to say which array it is.
So you'd want to change
focus="{{$index == selectedDevice.index}}"
to something like
focus="{{$index == selectedDevice.index && selectedDevice.kind == 'points'}}"
Where points is the category of the array where the code appears.
I sorted this one by downloading the most recent version of angularFire.js, seems like bower installed the on that didn't have this fix. now my contentEditable is!