I am creating a site that implements the Bing map control.
I have placed the pushpins, and they will show infoboxes when the user clicks on a pin.
What I need to do now is add actions to the infobox. I can do this statically with the action: option. I want to do it dynamically, as each site can have a different set of actions I want to present to the user.
I have built the string that has the actions in it, unfortunately the infobox wants an object, not a string, and I don't know which object it wants, nor how to turn the string into the proper object.
Any help at all would be appreciated.
Thanks!
Although you don't have a "setActions" you can use the "setOptions" on Infobox.
infobox.setOptions(infoboxOptions);
Ref: http://msdn.microsoft.com/en-us/library/gg675208.aspx
The options itself could be created like this, with just the actions:
var infoboxOptions = {
actions:[
{label: 'test1', eventHandler: testEvent1},
{label: 'test2', eventHandler: testEvent2}]};
Ref: http://msdn.microsoft.com/en-us/library/gg675210.aspx
You can call this anytime you want, thus adding for instance more actions to the infobox.
Now, you mention you have a string? I'm guessing you're talking about the JSON representation of the "infoboxOptions" or such. You can use something like
jQuery.parseJSON(jsonString); //if using jQuery
You can also do it programmatically, thus probably with some conditional logic:
var myActions = [];
if(A) {
myActions.push( {label: 'test1', eventHandler: testEvent1});
}
if(B) {
myActions.push( {label: 'test2', eventHandler: testEvent2});
}
if(C) {
myActions.push( {label: 'test3', eventHandler: testEvent3});
}
infobox.setOptions({ actions: myActions});
Related
I have this piece of code really confused me. I'm using typescript with vue (vuetify) and I'm still pretty new with typescript.
I have an array of objects that I want to load as items into a vuetify combobox.
Array =[
{
subject: 'science',
difficulty: 'medium'
}
{
subject: 'math',
difficulty: 'hard'
}]
with having the subject as the one visible on the dropdown and the difficulty will the the value hidden behind the combobox
i know it needs to look like this
items: [
{ text: 'science', value: 'medium' },
{ text: 'math', value: 'hard' }];
so i can load it on the v-combobox like this
<v-combobox :items="items" />
can anyone help me on how to achieve this? much appreciated!
I did not understand your issue but a typical combobox should be look like this:
(define selectedItem as an empty array in your data and call this.selectedItem.text)
<v-combobox
v-model="selectedItem"
:items="items"
item-value="value"
item-text="text"
:return-object="true"
label="Select an item.."
outlined
clearable
>
</v-combobox>
Yes for load the contents of array you set items props and also item-value et item-text props like #Aurora did. Because you an array of objects, and the component need to know what will be the value and the display field.
When I try to use uri, the image does not show and I want to avoid local images because I can't dynamically use require.
static propTypes = {
...ViewPropTypes,
initialPage: PropTypes.number,
pager: PropTypes.instanceOf(IndicatorViewPager),
tabs: PropTypes.arrayOf(PropTypes.shape({
text: PropTypes.string,
iconSource: Image.propTypes.source, <-- Here is the problem
selectedIconSource: Image.propTypes.source
})).isRequired,
}
Is there a way I can make this accept uri sources? Also here is the rest of my code:
let tabs = [{
text: `${this.state.tags.toLowerCase()}`,
iconSource: 'https://www.exmaple.com/img/cookies.png',
selectedIconSource: require("../img/bluep.png")
}];
I think you are mixing a couple of things. An Image source can be a require() or a uri, but the uri is not just a string you can pass to the source prop of the Image. It needs to be an object that has a uri string prop, like this:
<Image source={{uri: 'http://myimageurl.com'}}/>
Second, with prop types you are just defining which props validation you want to use at Debug time. It has nothing to do with your Image not showing up. If you send a wrong prop, it will show you a Yellow warning screen.
Lastly, your problem is that you are just sending the prop as a string, and you need to send the object.
So, without seeing much of the rest of the code, you should be fine changing this part:
let tabs = [{
text: `${this.state.tags.toLowerCase()}`,
iconSource: {uri: 'https://www.exmaple.com/img/cookies.png'},
selectedIconSource: require("../img/bluep.png")
}];
I have an issue, in a ng-click I have 2 expressions, and only one fires.
If I use only one expression at a time, they both work, but together they dont.
One is a function, and one is a simple: button = !button ; which I use to trigger the button state.
All of this is inside a ng-repeat, so I'll get multiple buttons, and each has to have its own state.
What I saw is that if instead of doing: button = !button which will only work alone, but not together with the function ( so ng-click= "func(); button = !button" won't fire the second expression).
but If I declare a simple bool in the controller like this:
button: boolean;
this.button = false;
then use: ng-click= "func(); $scope.button = !$scope.button"
It will fire both expression correctly, but the issue here is that I'm using a ng-repeat, so if 10buttons get generated, when you click one, with this solution, all the 10 buttons will get triggered because they are using the same bool.
So to avoid adding a new property on my list of objects that I loop over, just for the button state, is there a simpler solution?
I don't even understand why using a declared boolean in the controller would work, and using a simple: var = !var in the view won't.
I tried using instead a dummy function, with just a console.log return and it works, so it has also probably something to do with my function, but yet again, why would it work with a declared bool and not with a direct expression in the view?
the function is a bit long and calls other functions inside it, so for the purpose of my question I don't think it's relevant posting it and making a fiddle would also be complicated as the function takes data directly from the API.
But the important thing is that the function works correctly and it's used in multiple places in the project.
Thank you
You can try like the below code which will let you do what you are looking for, also please check this plunker for your example scenario.
Template:
<div ng-repeat="btn in buttonList">
<button type="button" value="btn.value" ng-click="func();btn.button=!btn.button" ng-disabled="btn.button">{{btn.name}}</button>
</div>
Controller:
$scope.buttonList = [{
name: 'World1',
value: 1
}, {
name: 'World2',
value: 2
}, {
name: 'World3',
value: 3
}, {
name: 'World4',
value: 4
}, {
name: 'World5',
value: 5
}, {
name: 'World6',
value: 6
}, {
name: 'World7',
value: 7
}, {
name: 'World8',
value: 8
}];
I am going through some React code while I am learning it. I have come across the shape method used in PropTypes, as I understood we use the shape method to validate if the given value is of certain shape, that we pass it as an argument. But, not sure what is it's purpose if we don't pass it any value that we want to validate, like in this example:
Field.propTypes = {
fields: PropTypes.shape().isRequired,
};
Can't we just have it like this:
Field.propTypes = {
fields: PropTypes.isRequired,
};
PropTypes is not for production usage it's used in the development environment and it's not the replacement of validation as some newbie people get it wrong.
For example, I had this dropdown component.
Dropdown.propTypes = {
// Notice this I define the shape of object here
item: PropTypes.shape({
value: PropTypes.string,
text: PropTypes.string,
}),
};
Developers who are supposed to use this component they are required to pass item object but the problem is this component will only work when the object has the particular shape like this.
{
value: "value1",
text: "text1",
},
So, what I did I defined the shape of the object that how item's object should be and if a someone pass wrong shaped object the component will throw the warning in console.
I'm new to ReactJS and am unsure about the best place to put validation logic that is needed both by nested child components in my form, and the overall "parent" form component itself. Here is a over-simplified example that illustrates my question...
I have a object like this that represents a pet owner:
{
name: 'Jon Arbuckle',
pets: [
{ name: 'Odie', type: 'dog' },
{ name: 'Garfield', type: 'cat' }
]
}
I'm using a composite component called <PetOwnerForm> to render a form for editing this data. <PetOwnerForm> renders something like this:
<input type="text" value={name} />
<PetList value={petOwner.pets} />
<PetList> is a composite component that renders this:
<PetListItem value={this.props.value[i]} /> // Render this for each pet...
// buttons for adding/deleting pets
<PetListItem> renders something like this:
<input type="text" value={this.props.value.name} />
<PetTypePicker value={this.props.value.type} />
Lastly, <PetTypePicker> renders a <select> with <option>s for pet types.
<PetTypePicker> needs to know how to validate the selected type so it can display an inline error message (e.g., ensure that a value is selected).
However, <PetOwnerForm> also needs to know how to validate the pet type because it needs to know how to validate the entire object (on load, each time the form is updated, and before submitting the data back to the server). If any field is invalid, the "Save" button should be disabled.
So where, for example, should the "is a valid pet type selected?" logic go? (Bear in mind that this is a trivial example; in reality I have many fields like this and nested composite components).
The options I see so far are:
A) Replicate the validation logic for pet type (or whatever field) both in <PetOwnerForm> and <PetTypePicker>. This might just be a matter of calling the same, shared validation function in both places:
//PetOwnerForm.js:
validate(petOwnerObj) {
Util.isPetTypeValid(petOwnerObj.pets[i]) // for each pet
// validate the other properties in petOwnerObj...
}
//PetTypePicker.js:
validate(petType) {
Util.isPetTypeValid(petType)
}
B) Use custom PetOwner, Pet, and PetType models that have their own validators. This way you can always ask a model to validate itself, regardless of where it is. Maybe this would look something like this:
{
name: { value: 'Jon Arbuckle', isValid: ()=>{...} },
pets: [
{
name: { value: 'Garfield', isValid: ()=>{...} },
type: { value: 'cat', isValid: ()=>{...} }
},
...
]
}
C) Modify PetOwnerForm.js go recurse the pet owner object, validating each value, and setting an 'errors' property that child components can reference, resulting in an object like this:
{
name: { value: 'Jon Arbuckle asdfasdfasdf^^', errors: ['Too many characters', 'Contains invalid character']] },
pets: [
{
name: { value: '', errors: ['Required value missing'] },
type: { value: 'tree', errors: ['Invalid pet type'] }
},
...
]
}
Which option is recommended for React apps (or is there another option)?
It's a nice elaborate question. This question is not specific to ReactJS applications. It applies to all frameworks that follow component model.
Following are my recommendations:
Differentiate between action driven validation and data format validation.
Low level components are aware of data format they accept, so they must validate for it. For example, postal-code, email, phone, SSN etc have fixed formats and their corresponding components must validate for the right input format.
Low level components are not aware of actions being performed on the overall data. For example, selection of pet-owner-type can be mandatory for "create" pet-owner action but can be optional for "save draft" action. So, low level components which are not aware of end action must not perform action driven validations.
Action driven validation must be performed by the higher level component aware of action, for example PetOwnerForm. Such validation result must be notified to low level components so that they can display appropriate errors. Every low level component must have an error state to support it.